From 50e0cbf4420325b29fe16340529d4f91abc68b5e Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Tue, 5 Aug 2025 19:00:02 +0200
Subject: [PATCH 01/45] feat: add VerticalCollapsibleSteps component for guided
user onboarding
---
.../components/flows/flow/actions.tsx | 2 +-
.../components/modals/user/welcome.tsx | 179 ++++++++---
.../steps/vertical-collapsible-steps.tsx | 303 ++++++++++++++++++
3 files changed, 446 insertions(+), 38 deletions(-)
create mode 100644 services/frontend/components/steps/vertical-collapsible-steps.tsx
diff --git a/services/frontend/components/flows/flow/actions.tsx b/services/frontend/components/flows/flow/actions.tsx
index 6470df29..692e6036 100644
--- a/services/frontend/components/flows/flow/actions.tsx
+++ b/services/frontend/components/flows/flow/actions.tsx
@@ -876,7 +876,7 @@ export default function Actions({
action.failure_pipeline_id ===
pipeline.id,
).length > 0
- ? "Assigned on Step"
+ ? "Assigned on Action"
: "Not Assigned"}
diff --git a/services/frontend/components/modals/user/welcome.tsx b/services/frontend/components/modals/user/welcome.tsx
index d5d028fb..eb943b31 100644
--- a/services/frontend/components/modals/user/welcome.tsx
+++ b/services/frontend/components/modals/user/welcome.tsx
@@ -10,30 +10,83 @@ import {
ModalBody,
ModalContent,
ModalFooter,
- ModalHeader,
+ Progress,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
-import React from "react";
+import React, { useState } from "react";
import ErrorCard from "@/components/error/ErrorCard";
import Welcomed from "@/lib/fetch/user/PUT/welcomed";
+import VerticalCollapsibleSteps from "@/components/steps/vertical-collapsible-steps";
export default function WelcomeModal({
disclosure,
}: {
disclosure: UseDisclosureReturn;
}) {
- const router = useRouter();
const { isOpen, onOpenChange } = disclosure;
- const [error, setError] = React.useState(false);
- const [errorText, setErrorText] = React.useState("");
- const [errorMessage, setErrorMessage] = React.useState("");
+ const [error, setError] = useState(false);
+ const [errorText, setErrorText] = useState("");
+ const [errorMessage, setErrorMessage] = useState("");
+
+ const [isLoading, setLoading] = useState(false);
+
+ const [currentStep, setCurrentStep] = useState(0);
+ const steps = [
+ {
+ title: "Create a project",
+ description:
+ "Projects are the foundation of your workflows. They help you organize your flows, invite team members or create runners.",
+ details: [
+ "Invite team members to collaborate on your project and flows.",
+ "Create or assign runners to execute your flows.",
+ "Generate API keys for secure and remote access to your project.",
+ "View audit logs to track changes and actions.",
+ ],
+ },
+ {
+ title: "Create a flow",
+ description:
+ "Flows are the core functionality of exFlow. They allow you to automate tasks and processes.",
+ details: [
+ "Specify the actions that will be taken when the flow is triggered.",
+ "Set up any conditions or filters to control the flow's behavior.",
+ "Define failover pipelines to handle errors or exceptions.",
+ ],
+ },
+ {
+ title: "Create actions within the flow",
+ description:
+ "Actions are the building blocks of your flows. They define what happens when the flow is triggered.",
+ details: [
+ "Actions are provided by the runner plugins.",
+ "Use plugins like terraform, ansible, git and many more to manage your infrastructure.",
+ "Create custom actions using the exFlow API to extend functionality.",
+ ],
+ },
+ {
+ title: "Enjoy",
+ description:
+ "Now that you have set up your project and flow, you can start using exFlow and we can't wait to see what you build.",
+ details: [
+ "Open Source and self-hosted.",
+ "Extensible with plugins to fit your needs.",
+ "Built with love by the exFlow team.",
+ ],
+ },
+ ];
async function handleSetWelcomed() {
+ setLoading(true);
+ setError(false);
+ setErrorText("");
+ setErrorMessage("");
+
+ // Call the API to set the welcomed status
const response = (await Welcomed()) as any;
if (!response) {
+ setLoading(false);
setError(true);
setErrorText("Failed to set welcomed status");
setErrorMessage("Failed to set welcomed status");
@@ -48,11 +101,13 @@ export default function WelcomeModal({
}
if (response.success) {
+ setLoading(false);
setError(false);
setErrorText("");
setErrorMessage("");
onOpenChange();
} else {
+ setLoading(false);
setError(true);
setErrorText(response.error);
setErrorMessage(response.message);
@@ -70,47 +125,97 @@ export default function WelcomeModal({
-
- {(onClose) => (
+
+ {() => (
<>
-
-
- New here, huh?
-
-
-
{error && (
)}
-
-
- Welcome to{" "}
- exFlow !
- We're thrilled to have you on board.
-
-
- This dialog will not be shown to you again.
-
-
+
+ Welcome to{" "}
+ exFlow !
+
+
+ This is your first time here, so we've prepared a short
+ guide to help you get started.
+
+
+
- {
- handleSetWelcomed();
- onOpenChange();
- }}
- >
-
- Start Exploring
-
+ {currentStep > 0 ? (
+
+ }
+ variant="flat"
+ onPress={() => {
+ setCurrentStep(currentStep - 1);
+ }}
+ >
+ Back
+
+ ) : (
+
+ }
+ variant="flat"
+ >
+ Back
+
+ )}
+ {currentStep + 1 === steps.length ? (
+
+ }
+ onPress={() => {
+ handleSetWelcomed();
+ }}
+ >
+ Start Exploring
+
+ ) : (
+
+ }
+ onPress={() => setCurrentStep(currentStep + 1)}
+ >
+ Next Step
+
+ )}
>
)}
diff --git a/services/frontend/components/steps/vertical-collapsible-steps.tsx b/services/frontend/components/steps/vertical-collapsible-steps.tsx
new file mode 100644
index 00000000..8a42a5a9
--- /dev/null
+++ b/services/frontend/components/steps/vertical-collapsible-steps.tsx
@@ -0,0 +1,303 @@
+"use client";
+
+import type { ComponentProps } from "react";
+import type { ButtonProps } from "@heroui/react";
+
+import React from "react";
+import { Spacer } from "@heroui/react";
+import { useControlledState } from "@react-stately/utils";
+import { m, LazyMotion, domAnimation } from "framer-motion";
+import { cn } from "@heroui/react";
+
+export type VerticalCollapsibleStepProps = {
+ className?: string;
+ description?: React.ReactNode;
+ title?: React.ReactNode;
+ details?: string[];
+};
+
+export interface VerticalCollapsibleStepsProps
+ // eslint-disable-next-line no-undef
+ extends React.HTMLAttributes {
+ /**
+ * An array of steps.
+ *
+ * @default []
+ */
+ steps?: VerticalCollapsibleStepProps[];
+ /**
+ * The color of the steps.
+ *
+ * @default "primary"
+ */
+ color?: ButtonProps["color"];
+ /**
+ * The current step index.
+ */
+ currentStep?: number;
+ /**
+ * The default step index.
+ *
+ * @default 0
+ */
+ defaultStep?: number;
+ /**
+ * The custom class for the steps wrapper.
+ */
+ className?: string;
+ /**
+ * The custom class for the step.
+ */
+ stepClassName?: string;
+ /**
+ * Callback function when the step index changes.
+ */
+ onStepChange?: (stepIndex: number) => void;
+}
+
+function CheckIcon(props: ComponentProps<"svg">) {
+ return (
+
+
+
+ );
+}
+
+const VerticalCollapsibleSteps = React.forwardRef<
+ // eslint-disable-next-line no-undef
+ HTMLButtonElement,
+ VerticalCollapsibleStepsProps
+>(
+ (
+ {
+ color = "primary",
+ steps = [],
+ defaultStep = 0,
+ onStepChange,
+ currentStep: currentStepProp,
+ stepClassName,
+ className,
+ ...props
+ },
+ ref,
+ ) => {
+ const [currentStep, setCurrentStep] = useControlledState(
+ currentStepProp,
+ defaultStep,
+ onStepChange,
+ );
+
+ const colors = React.useMemo(() => {
+ let userColor;
+ let fgColor;
+
+ const colorsVars = [
+ "[--active-fg-color:hsl(var(--step-fg-color))]",
+ "[--active-border-color:hsl(var(--step-color))]",
+ "[--active-color:hsl(var(--step-color))]",
+ "[--complete-background-color:hsl(var(--step-color))]",
+ "[--complete-border-color:hsl(var(--step-color))]",
+ "[--inactive-border-color:hsl(var(--heroui-default-300))]",
+ "[--inactive-color:hsl(var(--heroui-default-300))]",
+ ];
+
+ switch (color) {
+ case "primary":
+ userColor = "[--step-color:var(--heroui-primary)]";
+ fgColor = "[--step-fg-color:var(--heroui-primary-foreground)]";
+ break;
+ case "secondary":
+ userColor = "[--step-color:var(--heroui-secondary)]";
+ fgColor = "[--step-fg-color:var(--heroui-secondary-foreground)]";
+ break;
+ case "success":
+ userColor = "[--step-color:var(--heroui-success)]";
+ fgColor = "[--step-fg-color:var(--heroui-success-foreground)]";
+ break;
+ case "warning":
+ userColor = "[--step-color:var(--heroui-warning)]";
+ fgColor = "[--step-fg-color:var(--heroui-warning-foreground)]";
+ break;
+ case "danger":
+ userColor = "[--step-color:var(--heroui-error)]";
+ fgColor = "[--step-fg-color:var(--heroui-error-foreground)]";
+ break;
+ case "default":
+ userColor = "[--step-color:var(--heroui-default)]";
+ fgColor = "[--step-fg-color:var(--heroui-default-foreground)]";
+ break;
+ default:
+ userColor = "[--step-color:var(--heroui-primary)]";
+ fgColor = "[--step-fg-color:var(--heroui-primary-foreground)]";
+ break;
+ }
+
+ colorsVars.unshift(fgColor);
+ colorsVars.unshift(userColor);
+
+ return colorsVars;
+ }, [color]);
+
+ return (
+
+
+ {steps?.map((step, stepIdx) => {
+ let status =
+ currentStep === stepIdx
+ ? "active"
+ : currentStep < stepIdx
+ ? "inactive"
+ : "complete";
+
+ return (
+
+
+
setCurrentStep(stepIdx)}
+ {...props}
+ >
+
+
+
+
+
+ {status === "complete" ? (
+
+ ) : (
+ {stepIdx + 1}
+ )}
+
+
+
+
+
+
+
+
+ {step.title}
+
+
+ {step.description}
+
+
+
+
+
+ {step.details && step.details?.length > 0 && (
+
+
+
+
+ {step.details.map((detail, idx) => (
+
+ {detail}
+
+ ))}
+
+
+
+ )}
+
+ );
+ })}
+
+
+ );
+ },
+);
+
+VerticalCollapsibleSteps.displayName = "VerticalCollapsibleSteps";
+
+export default VerticalCollapsibleSteps;
From 919e259f1efd58134e69fbc2990098c8c2ff57a7 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Mon, 18 Aug 2025 14:55:28 +0200
Subject: [PATCH 02/45] feat: Implement project encryption management
- Updated project model to include encryption key and status.
- Added functions to enable, disable, and rotate encryption keys for projects.
- Integrated encryption checks in various execution and flow handlers.
- Enhanced error handling for encryption-related operations.
- Added new API endpoints for managing project encryption.
- Updated frontend to display encryption status for projects.
- Migrated existing projects to support new encryption features.
---
.gitignore | 1 +
ENCRYPTION_SECURITY.md | 125 ++++++++++++++
services/backend/config/config.yaml | 7 +-
services/backend/config/main.go | 10 +-
.../database/migrations/10_flows_type_col.go | 60 +++++++
.../migrations/7_project_encryption_keys.go | 67 ++++++++
.../8_settings_encryption_migration.go | 60 +++++++
.../migrations/9_remove_flows_cols.go | 55 ++++++
.../checkForFlowActionUpdates.go | 26 +--
.../checkHangingExecutionSteps.go | 15 +-
.../checkHangingExecutions.go | 19 ++-
.../checkScheduledExecutions.go | 19 ++-
.../scheduleFlowExecutions.go | 19 ++-
.../backend/functions/encryption/migration.go | 146 ++++++++++++++++
.../functions/encryption/old_encryption.go | 160 ++++++++++++++++++
.../backend/functions/encryption/payload.go | 63 -------
...ssage.go => project_execution_messages.go} | 22 ++-
.../functions/encryption/project_keys.go | 148 ++++++++++++++++
.../{params.go => project_params.go} | 97 +++++++++--
services/backend/go.mod | 2 +-
services/backend/go.sum | 4 +-
.../handlers/executions/create_step.go | 11 +-
.../backend/handlers/executions/get_step.go | 21 ++-
.../backend/handlers/executions/get_steps.go | 18 +-
.../backend/handlers/executions/schedule.go | 12 +-
.../handlers/executions/update_step.go | 15 +-
.../backend/handlers/flows/add_actions.go | 13 +-
.../flows/add_failure_pipeline_actions.go | 13 +-
services/backend/handlers/flows/get_flow.go | 15 +-
services/backend/handlers/flows/get_flows.go | 46 ++---
.../backend/handlers/flows/start_execution.go | 12 +-
services/backend/handlers/flows/update.go | 6 -
.../backend/handlers/flows/update_actions.go | 13 +-
.../handlers/flows/update_actions_details.go | 21 +--
.../handlers/flows/update_failure_pipeline.go | 13 +-
.../flows/update_failure_pipeline_actions.go | 13 +-
services/backend/handlers/projects/create.go | 12 +-
.../backend/handlers/projects/encryption.go | 152 +++++++++++++++++
services/backend/main.go | 19 ++-
services/backend/pkg/models/projects.go | 2 +
services/backend/pkg/models/settings.go | 1 +
services/backend/router/projects.go | 14 ++
.../frontend/components/projects/project.tsx | 21 ++-
43 files changed, 1389 insertions(+), 199 deletions(-)
create mode 100644 ENCRYPTION_SECURITY.md
create mode 100644 services/backend/database/migrations/10_flows_type_col.go
create mode 100644 services/backend/database/migrations/7_project_encryption_keys.go
create mode 100644 services/backend/database/migrations/8_settings_encryption_migration.go
create mode 100644 services/backend/database/migrations/9_remove_flows_cols.go
create mode 100644 services/backend/functions/encryption/migration.go
create mode 100644 services/backend/functions/encryption/old_encryption.go
delete mode 100644 services/backend/functions/encryption/payload.go
rename services/backend/functions/encryption/{execution_step_action_message.go => project_execution_messages.go} (65%)
create mode 100644 services/backend/functions/encryption/project_keys.go
rename services/backend/functions/encryption/{params.go => project_params.go} (67%)
create mode 100644 services/backend/handlers/projects/encryption.go
diff --git a/.gitignore b/.gitignore
index 64349e68..17399d40 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,6 +43,7 @@ services/backend/*.exe~
services/backend/*.dll
services/backend/*.so
services/backend/*.dylib
+services/backend/*.sql
# Test binary, built with `go test -c`
services/backend/*.test
diff --git a/ENCRYPTION_SECURITY.md b/ENCRYPTION_SECURITY.md
new file mode 100644
index 00000000..34692939
--- /dev/null
+++ b/ENCRYPTION_SECURITY.md
@@ -0,0 +1,125 @@
+# Secure Project-Based Encryption Setup
+
+## Overview
+
+The enhanced encryption system now uses **key derivation** instead of storing encryption keys directly in the database. This significantly improves security by ensuring that even if someone gains access to your database, they cannot decrypt the data without the master secret.
+
+## How It Works
+
+1. **Master Secret**: A single secret stored outside the database (environment variable, config file, external key management system)
+2. **Project Salts**: Random salts generated per project and stored in the database
+3. **Key Derivation**: Encryption keys are derived using PBKDF2(master_secret + project_salt)
+
+Even if an attacker gains access to your database, they only see:
+- Encrypted data
+- Random salts (which are useless without the master secret)
+
+## Configuration
+
+### Option 1: Environment Variable (Recommended for Production)
+```bash
+# Set the master secret as an environment variable
+export EXFLOW_ENCRYPTION_MASTER_SECRET="your-very-long-and-secure-master-secret-here"
+```
+
+### Option 2: Configuration File
+```yaml
+# In your backend config.yaml
+encryption:
+ master_secret: "your-very-long-and-secure-master-secret-here"
+ # Fallback key for legacy data (optional)
+ key: "legacy-key-for-backward-compatibility"
+```
+
+### Option 3: External Key Management (For Enterprise)
+```yaml
+# For advanced setups, integrate with:
+# - AWS KMS
+# - HashiCorp Vault
+# - Azure Key Vault
+# - Google Cloud KMS
+```
+
+## Master Secret Requirements
+
+- **Length**: Minimum 32 characters, recommended 64+ characters
+- **Randomness**: Use a cryptographically secure random generator
+- **Characters**: Include letters, numbers, and symbols
+- **Uniqueness**: Must be unique per exFlow installation
+
+### Generate a Secure Master Secret
+
+```bash
+# Option 1: Using OpenSSL
+openssl rand -base64 64
+
+# Option 2: Using Python
+python3 -c "import secrets; print(secrets.token_urlsafe(64))"
+
+# Option 3: Using Go
+go run -c "package main; import (\"crypto/rand\", \"encoding/base64\", \"fmt\"); func main() { b := make([]byte, 64); rand.Read(b); fmt.Println(base64.URLEncoding.EncodeToString(b)) }"
+```
+
+## Security Benefits
+
+1. **Database Compromise Protection**: Even with full database access, encrypted data remains secure
+2. **Per-Project Isolation**: Each project uses a unique derived key
+3. **Key Rotation**: Changing the master secret or project salt rotates all encryption
+4. **Audit Trail**: Key derivation can be logged and monitored
+5. **Compliance**: Meets most regulatory requirements for encryption key management
+
+## Migration from Legacy System
+
+The system maintains backward compatibility:
+
+1. **New Projects**: Automatically use the secure key derivation system
+2. **Existing Projects**: Continue working with existing keys until migrated
+3. **Gradual Migration**: Projects can be migrated one by one using the key rotation feature
+
+## Best Practices
+
+### Storage
+- **Never** store the master secret in the database
+- Use environment variables or external key management systems
+- Rotate the master secret periodically (quarterly/annually)
+- Keep secure backups of the master secret
+
+### Access Control
+- Limit access to the master secret to essential personnel only
+- Use separate master secrets for different environments (dev/staging/prod)
+- Log all access to encryption keys
+
+### Monitoring
+- Monitor for unusual encryption/decryption patterns
+- Alert on encryption failures
+- Regular security audits of key management processes
+
+## Troubleshooting
+
+### "Master secret not configured" Error
+1. Ensure the master secret is set in your configuration
+2. Restart the backend service after setting the secret
+3. Check environment variable spelling
+
+### "Failed to decrypt" Errors
+1. Verify the master secret hasn't changed
+2. Check if the project salt was corrupted
+3. Consider falling back to legacy key mode temporarily
+
+### Performance Considerations
+- Key derivation adds ~1-2ms per operation
+- Consider caching derived keys in memory for high-throughput scenarios
+- Monitor CPU usage during bulk encryption operations
+
+## Example Implementation
+
+```go
+// Environment variable
+masterSecret := os.Getenv("EXFLOW_ENCRYPTION_MASTER_SECRET")
+
+// Or AWS Secrets Manager
+masterSecret := getFromAWSSecretsManager("exflow/encryption/master-secret")
+
+// Or HashiCorp Vault
+masterSecret := getFromVault("secret/exflow/encryption/master-secret")
+```
diff --git a/services/backend/config/config.yaml b/services/backend/config/config.yaml
index 03826a27..e9f26b73 100644
--- a/services/backend/config/config.yaml
+++ b/services/backend/config/config.yaml
@@ -12,9 +12,10 @@ database:
password: postgres
encryption:
- enabled: true
- # maximum 32 characters
- key: null
+ # Minimum 32 characters, recommended 64+ characters
+ master_secret: "your-very-long-and-secure-master-secret-here"
+ # Fallback key for legacy data (optional)
+ key: "legacy-key-for-backward-compatibility"
jwt:
secret: null
diff --git a/services/backend/config/main.go b/services/backend/config/main.go
index 6e38ef71..07956031 100644
--- a/services/backend/config/main.go
+++ b/services/backend/config/main.go
@@ -46,8 +46,8 @@ type JWTConf struct {
}
type EncryptionConf struct {
- Enabled bool `mapstructure:"enabled" validate:"required"`
- Key string `mapstructure:"key"`
+ Key string `mapstructure:"key"`
+ MasterSecret string `mapstructure:"master_secret" validate:"required"`
}
type RunnerConf struct {
@@ -84,8 +84,8 @@ func (cm *ConfigurationManager) LoadConfig(configFile string) error {
"database.name": "BACKEND_DATABASE_NAME",
"database.user": "BACKEND_DATABASE_USER",
"database.password": "BACKEND_DATABASE_PASSWORD",
- "encryption.enabled": "BACKEND_ENCRYPTION_ENABLED",
"encryption.key": "BACKEND_ENCRYPTION_KEY",
+ "encryption.master_secret": "BACKEND_ENCRYPTION_MASTER_SECRET",
"jwt.secret": "BACKEND_JWT_SECRET",
"runner.shared_runner_secret": "BACKEND_RUNNER_SHARED_RUNNER_SECRET",
}
@@ -118,6 +118,10 @@ func (cm *ConfigurationManager) LoadConfig(configFile string) error {
// Assign to package-level variable for global access
Config = &config
+ if config.Encryption.MasterSecret == "" {
+ log.Fatal("Master secret is required for encryption")
+ }
+
log.WithFields(log.Fields{
"file": configFile,
"content": cm.viper.AllSettings(),
diff --git a/services/backend/database/migrations/10_flows_type_col.go b/services/backend/database/migrations/10_flows_type_col.go
new file mode 100644
index 00000000..e5bdc6f5
--- /dev/null
+++ b/services/backend/database/migrations/10_flows_type_col.go
@@ -0,0 +1,60 @@
+package migrations
+
+import (
+ "context"
+ "fmt"
+
+ log "github.com/sirupsen/logrus"
+ "github.com/uptrace/bun"
+)
+
+func init() {
+ Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
+ return addTypeToFlows(ctx, db)
+ }, func(ctx context.Context, db *bun.DB) error {
+ return removeTypeFromFlows(ctx, db)
+ })
+}
+
+func addTypeToFlows(ctx context.Context, db *bun.DB) error {
+ // add type column
+ exists, err := columnExists(ctx, db, "flows", "type")
+ if err != nil {
+ return fmt.Errorf("failed to check if type column exists: %v", err)
+ }
+ if !exists {
+ _, err := db.NewAddColumn().
+ Table("flows").
+ ColumnExpr("type TEXT DEFAULT 'default'").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to add type column to flows table: %v", err)
+ }
+ } else {
+ log.Debug("type column already exists in flows table")
+ }
+
+ return nil
+}
+
+func removeTypeFromFlows(ctx context.Context, db *bun.DB) error {
+ exists, err := columnExists(ctx, db, "flows", "type")
+ if err != nil {
+ return fmt.Errorf("failed to check if type column exists: %v", err)
+ }
+ if exists {
+ _, err := db.NewDropColumn().
+ Table("flows").
+ Column("type").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to remove type column from flows table: %v", err)
+ }
+ } else {
+ log.Debug("type column already removed from flows table")
+ }
+
+ return nil
+}
diff --git a/services/backend/database/migrations/7_project_encryption_keys.go b/services/backend/database/migrations/7_project_encryption_keys.go
new file mode 100644
index 00000000..e7c7bf94
--- /dev/null
+++ b/services/backend/database/migrations/7_project_encryption_keys.go
@@ -0,0 +1,67 @@
+package migrations
+
+import (
+ "context"
+ "crypto/rand"
+ "encoding/hex"
+
+ "github.com/uptrace/bun"
+)
+
+func init() {
+ Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
+ // Add encryption_key column to projects table
+ _, err := db.ExecContext(ctx, "ALTER TABLE projects ADD COLUMN IF NOT EXISTS encryption_key TEXT DEFAULT ''")
+ if err != nil {
+ return err
+ }
+
+ // Add encryption_enabled column to projects table
+ _, err = db.ExecContext(ctx, "ALTER TABLE projects ADD COLUMN IF NOT EXISTS encryption_enabled BOOLEAN DEFAULT true")
+ if err != nil {
+ return err
+ }
+
+ // Generate encryption salts for existing projects that don't have them
+ rows, err := db.QueryContext(ctx, "SELECT id FROM projects WHERE encryption_key = '' OR encryption_key IS NULL")
+ if err != nil {
+ return err
+ }
+ defer rows.Close()
+
+ for rows.Next() {
+ var projectID string
+ if err := rows.Scan(&projectID); err != nil {
+ continue // Skip problematic rows, don't fail the entire migration
+ }
+
+ // Generate a new 32-byte salt (not a key!)
+ salt := make([]byte, 32)
+ if _, err := rand.Read(salt); err != nil {
+ continue // Skip if salt generation fails
+ }
+ hexSalt := hex.EncodeToString(salt)
+
+ // Update the project with the new encryption salt
+ _, err = db.ExecContext(ctx, "UPDATE projects SET encryption_key = $1, encryption_enabled = true WHERE id = $2", hexSalt, projectID)
+ if err != nil {
+ continue // Skip if update fails
+ }
+ }
+
+ return nil
+ }, func(ctx context.Context, db *bun.DB) error {
+ // Drop the added columns
+ _, err := db.ExecContext(ctx, "ALTER TABLE projects DROP COLUMN IF EXISTS encryption_key")
+ if err != nil {
+ return err
+ }
+
+ _, err = db.ExecContext(ctx, "ALTER TABLE projects DROP COLUMN IF EXISTS encryption_enabled")
+ if err != nil {
+ return err
+ }
+
+ return nil
+ })
+}
diff --git a/services/backend/database/migrations/8_settings_encryption_migration.go b/services/backend/database/migrations/8_settings_encryption_migration.go
new file mode 100644
index 00000000..61e6ae2c
--- /dev/null
+++ b/services/backend/database/migrations/8_settings_encryption_migration.go
@@ -0,0 +1,60 @@
+package migrations
+
+import (
+ "context"
+ "fmt"
+
+ log "github.com/sirupsen/logrus"
+ "github.com/uptrace/bun"
+)
+
+func init() {
+ Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
+ return addNewEncryptionMigratedToSettings(ctx, db)
+ }, func(ctx context.Context, db *bun.DB) error {
+ return removeNewEncryptionMigratedFromSettings(ctx, db)
+ })
+}
+
+func addNewEncryptionMigratedToSettings(ctx context.Context, db *bun.DB) error {
+ // add new_encryption_migrated column
+ exists, err := columnExists(ctx, db, "settings", "new_encryption_migrated")
+ if err != nil {
+ return fmt.Errorf("failed to check if new_encryption_migrated column exists: %v", err)
+ }
+ if !exists {
+ _, err := db.NewAddColumn().
+ Table("settings").
+ ColumnExpr("new_encryption_migrated BOOLEAN DEFAULT FALSE").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to add new_encryption_migrated column to settings table: %v", err)
+ }
+ } else {
+ log.Debug("new_encryption_migrated column already exists in settings table")
+ }
+
+ return nil
+}
+
+func removeNewEncryptionMigratedFromSettings(ctx context.Context, db *bun.DB) error {
+ exists, err := columnExists(ctx, db, "settings", "new_encryption_migrated")
+ if err != nil {
+ return fmt.Errorf("failed to check if new_encryption_migrated column exists: %v", err)
+ }
+ if exists {
+ _, err := db.NewDropColumn().
+ Table("settings").
+ Column("new_encryption_migrated").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to remove new_encryption_migrated column from settings table: %v", err)
+ }
+ } else {
+ log.Debug("new_encryption_migrated column already removed from settings table")
+ }
+
+ return nil
+}
diff --git a/services/backend/database/migrations/9_remove_flows_cols.go b/services/backend/database/migrations/9_remove_flows_cols.go
new file mode 100644
index 00000000..5437f901
--- /dev/null
+++ b/services/backend/database/migrations/9_remove_flows_cols.go
@@ -0,0 +1,55 @@
+package migrations
+
+import (
+ "context"
+ "fmt"
+
+ log "github.com/sirupsen/logrus"
+ "github.com/uptrace/bun"
+)
+
+func init() {
+ Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
+ return removeColsFromFlow(ctx, db)
+ }, func(ctx context.Context, db *bun.DB) error {
+ return removeColsFromFlow(ctx, db)
+ })
+}
+
+func removeColsFromFlow(ctx context.Context, db *bun.DB) error {
+ exists, err := columnExists(ctx, db, "flows", "encrypt_action_params")
+ if err != nil {
+ return fmt.Errorf("failed to check if encrypt_action_params column exists: %v", err)
+ }
+ if exists {
+ _, err := db.NewDropColumn().
+ Table("flows").
+ Column("encrypt_action_params").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to remove encrypt_action_params column from flows table: %v", err)
+ }
+ } else {
+ log.Debug("encrypt_action_params column already removed from flows table")
+ }
+
+ exists, err = columnExists(ctx, db, "flows", "encrypt_executions")
+ if err != nil {
+ return fmt.Errorf("failed to check if encrypt_executions column exists: %v", err)
+ }
+ if exists {
+ _, err := db.NewDropColumn().
+ Table("flows").
+ Column("encrypt_executions").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to remove encrypt_executions column from flows table: %v", err)
+ }
+ } else {
+ log.Debug("encrypt_executions column already removed from flows table")
+ }
+
+ return nil
+}
diff --git a/services/backend/functions/background_checks/checkForFlowActionUpdates.go b/services/backend/functions/background_checks/checkForFlowActionUpdates.go
index de42daaa..1cbba7e6 100644
--- a/services/backend/functions/background_checks/checkForFlowActionUpdates.go
+++ b/services/backend/functions/background_checks/checkForFlowActionUpdates.go
@@ -5,7 +5,6 @@ import (
"strings"
"github.com/Masterminds/semver"
- "github.com/v1Flows/exFlow/services/backend/config"
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
shared_models "github.com/v1Flows/shared-library/pkg/models"
@@ -54,10 +53,17 @@ func processFlowsForProject(db *bun.DB, context context.Context, projectID strin
return
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", projectID).Scan(context)
+ if err != nil {
+ return
+ }
+
// Process each flow
for _, flow := range flows {
updatedFlow := deepcopy.Copy(flow).(models.Flows) // Deep copy the flow
- updateFlowActions(&updatedFlow, runners)
+ updateFlowActions(&updatedFlow, runners, project, db)
// Write updated flow to the database
_, err := db.NewUpdate().Model(&updatedFlow).Where("id = ?", updatedFlow.ID).Set("failure_pipelines = ?, actions = ?", updatedFlow.FailurePipelines, updatedFlow.Actions).Exec(context)
@@ -67,7 +73,7 @@ func processFlowsForProject(db *bun.DB, context context.Context, projectID strin
}
}
-func updateFlowActions(flow *models.Flows, runners []models.Runners) {
+func updateFlowActions(flow *models.Flows, runners []models.Runners, project models.Projects, db *bun.DB) {
// Check for action updates in the flow itself
for j, action := range flow.Actions {
if len(runners) == 0 {
@@ -78,7 +84,7 @@ func updateFlowActions(flow *models.Flows, runners []models.Runners) {
flow.Actions[j] = action
}
} else {
- updatedAction := updateActionIfNeeded(flow, action, runners)
+ updatedAction := updateActionIfNeeded(flow, action, runners, project, db)
flow.Actions[j] = updatedAction
}
}
@@ -96,7 +102,7 @@ func updateFlowActions(flow *models.Flows, runners []models.Runners) {
updatedPipeline.Actions[j] = action
}
} else {
- updatedAction := updateActionIfNeeded(flow, action, runners)
+ updatedAction := updateActionIfNeeded(flow, action, runners, project, db)
updatedPipeline.Actions[j] = updatedAction
}
}
@@ -104,7 +110,7 @@ func updateFlowActions(flow *models.Flows, runners []models.Runners) {
}
}
-func updateActionIfNeeded(flow *models.Flows, action shared_models.Action, runners []models.Runners) shared_models.Action {
+func updateActionIfNeeded(flow *models.Flows, action shared_models.Action, runners []models.Runners, project models.Projects, db *bun.DB) shared_models.Action {
for _, runner := range runners {
for _, plugin := range runner.Plugins {
if action.Plugin == strings.ToLower(plugin.Name) {
@@ -121,7 +127,7 @@ func updateActionIfNeeded(flow *models.Flows, action shared_models.Action, runne
}
if pluginVersion.GreaterThan(actionVersion) {
- return createUpdatedAction(flow, action, plugin)
+ return createUpdatedAction(flow, action, plugin, project, db)
}
}
}
@@ -129,7 +135,7 @@ func updateActionIfNeeded(flow *models.Flows, action shared_models.Action, runne
return action
}
-func createUpdatedAction(flow *models.Flows, action shared_models.Action, plugin shared_models.Plugin) shared_models.Action {
+func createUpdatedAction(flow *models.Flows, action shared_models.Action, plugin shared_models.Plugin, project models.Projects, db *bun.DB) shared_models.Action {
updatedAction := deepcopy.Copy(action).(shared_models.Action) // Deep copy the action
updatedAction.UpdateAvailable = true
updatedAction.UpdateVersion = plugin.Version
@@ -150,9 +156,9 @@ func createUpdatedAction(flow *models.Flows, action shared_models.Action, plugin
// Otherwise, use the default value
updatedAction.UpdatedAction.Params[uP].Value = updatedParam.Default
- if config.Config.Encryption.Enabled && flow.EncryptActionParams {
+ if project.EncryptionEnabled {
var err error
- updatedAction.UpdatedAction.Params[uP], err = encryption.EncryptParam(updatedAction.UpdatedAction.Params[uP])
+ updatedAction.UpdatedAction.Params[uP], err = encryption.EncryptParamWithProject(updatedAction.UpdatedAction.Params[uP], project.ID.String(), db)
if err != nil {
log.Errorf("Bot: Error encrypting action param %s: %v", updatedAction.UpdatedAction.Params[uP].Key, err)
}
diff --git a/services/backend/functions/background_checks/checkHangingExecutionSteps.go b/services/backend/functions/background_checks/checkHangingExecutionSteps.go
index d05072b1..a8b69eba 100644
--- a/services/backend/functions/background_checks/checkHangingExecutionSteps.go
+++ b/services/backend/functions/background_checks/checkHangingExecutionSteps.go
@@ -42,11 +42,18 @@ func checkHangingExecutionSteps(db *bun.DB) {
continue
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
+ if err != nil {
+ return
+ }
+
// if the execution is finished, let the step fail
if execution.Status == "success" || execution.Status == "error" || execution.Status == "canceled" || execution.Status == "noPatternMatch" || execution.Status == "recovered" {
// check for encryption and decrypt messages
- if flow.EncryptExecutions && step.Messages != nil && len(step.Messages) > 0 {
- step.Messages, err = encryption.DecryptExecutionStepActionMessage(step.Messages)
+ if project.EncryptionEnabled && step.Messages != nil && len(step.Messages) > 0 {
+ step.Messages, err = encryption.DecryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
}
@@ -68,8 +75,8 @@ func checkHangingExecutionSteps(db *bun.DB) {
})
// check for encryption and encrypt messages
- if flow.EncryptExecutions && step.Messages != nil && len(step.Messages) > 0 {
- step.Messages, err = encryption.EncryptExecutionStepActionMessage(step.Messages)
+ if project.EncryptionEnabled && step.Messages != nil && len(step.Messages) > 0 {
+ step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
}
diff --git a/services/backend/functions/background_checks/checkHangingExecutions.go b/services/backend/functions/background_checks/checkHangingExecutions.go
index 2021416c..e3c94863 100644
--- a/services/backend/functions/background_checks/checkHangingExecutions.go
+++ b/services/backend/functions/background_checks/checkHangingExecutions.go
@@ -38,6 +38,13 @@ func checkHangingExecutions(db *bun.DB) {
log.Error("Bot: Error getting flow data", err)
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
+ if err != nil {
+ return
+ }
+
step := shared_models.ExecutionSteps{
ExecutionID: execution.ID.String(),
Action: shared_models.Action{
@@ -68,8 +75,8 @@ func checkHangingExecutions(db *bun.DB) {
}
// check for encryption
- if flow.EncryptExecutions && step.Messages != nil && len(step.Messages) > 0 {
- step.Messages, err = encryption.EncryptExecutionStepActionMessage(step.Messages)
+ if project.EncryptionEnabled && step.Messages != nil && len(step.Messages) > 0 {
+ step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
}
@@ -103,8 +110,8 @@ func checkHangingExecutions(db *bun.DB) {
step.CanceledBy = "Automated Check"
// check for encryption and decrypt messages
- if flow.EncryptExecutions && step.Messages != nil && len(step.Messages) > 0 {
- step.Messages, err = encryption.DecryptExecutionStepActionMessage(step.Messages)
+ if project.EncryptionEnabled && step.Messages != nil && len(step.Messages) > 0 {
+ step.Messages, err = encryption.DecryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
}
@@ -124,8 +131,8 @@ func checkHangingExecutions(db *bun.DB) {
})
// check for encryption and encrypt messages
- if flow.EncryptExecutions && step.Messages != nil && len(step.Messages) > 0 {
- step.Messages, err = encryption.EncryptExecutionStepActionMessage(step.Messages)
+ if project.EncryptionEnabled && step.Messages != nil && len(step.Messages) > 0 {
+ step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
}
diff --git a/services/backend/functions/background_checks/checkScheduledExecutions.go b/services/backend/functions/background_checks/checkScheduledExecutions.go
index fa444397..b36fe007 100644
--- a/services/backend/functions/background_checks/checkScheduledExecutions.go
+++ b/services/backend/functions/background_checks/checkScheduledExecutions.go
@@ -33,6 +33,13 @@ func checkScheduledExecutions(db *bun.DB) {
log.Error("Bot: Error getting flow data", err)
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
+ if err != nil {
+ return
+ }
+
// update the scheduled step to success
var steps []models.ExecutionSteps
err = db.NewSelect().Model(&steps).Where("execution_id = ?", execution.ID).Scan(context)
@@ -47,8 +54,8 @@ func checkScheduledExecutions(db *bun.DB) {
step.FinishedAt = time.Now()
// check for encryption
- if flow.EncryptExecutions && step.Messages != nil && len(step.Messages) > 0 {
- step.Messages, err = encryption.DecryptExecutionStepActionMessage(step.Messages)
+ if project.EncryptionEnabled && step.Messages != nil && len(step.Messages) > 0 {
+ step.Messages, err = encryption.DecryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
}
@@ -68,8 +75,8 @@ func checkScheduledExecutions(db *bun.DB) {
})
// check for encryption
- if flow.EncryptExecutions && step.Messages != nil && len(step.Messages) > 0 {
- step.Messages, err = encryption.EncryptExecutionStepActionMessage(step.Messages)
+ if project.EncryptionEnabled && step.Messages != nil && len(step.Messages) > 0 {
+ step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
}
@@ -106,8 +113,8 @@ func checkScheduledExecutions(db *bun.DB) {
}
// check for encryption
- if flow.EncryptExecutions && step.Messages != nil && len(step.Messages) > 0 {
- step.Messages, err = encryption.EncryptExecutionStepActionMessage(step.Messages)
+ if project.EncryptionEnabled && step.Messages != nil && len(step.Messages) > 0 {
+ step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
}
diff --git a/services/backend/functions/background_checks/scheduleFlowExecutions.go b/services/backend/functions/background_checks/scheduleFlowExecutions.go
index 30ca944c..38d517ee 100644
--- a/services/backend/functions/background_checks/scheduleFlowExecutions.go
+++ b/services/backend/functions/background_checks/scheduleFlowExecutions.go
@@ -27,6 +27,13 @@ func scheduleFlowExecutions(db *bun.DB) {
// schedule new executions for each flow based on the schedule
for _, flow := range flows {
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
+ if err != nil {
+ return
+ }
+
// get all executions for that flow that are triggered by schedule
var lastScheduledExecution []models.Executions
count, err := db.NewSelect().
@@ -46,10 +53,10 @@ func scheduleFlowExecutions(db *bun.DB) {
var currentTime time.Time
if count == 0 {
currentTime = time.Now()
- returnedExecutionTime := createExecution(currentTime, flow, db, context)
+ returnedExecutionTime := createExecution(currentTime, flow, db, context, project)
// directly schedule the next execution
- createExecution(returnedExecutionTime, flow, db, context)
+ createExecution(returnedExecutionTime, flow, db, context, project)
} else {
currentTime = lastScheduledExecution[0].ScheduledAt
@@ -57,13 +64,13 @@ func scheduleFlowExecutions(db *bun.DB) {
currentTime = time.Now()
}
- createExecution(currentTime, flow, db, context)
+ createExecution(currentTime, flow, db, context, project)
}
}
}
-func createExecution(currentTime time.Time, flow models.Flows, db *bun.DB, context context.Context) (scheduledAt time.Time) {
+func createExecution(currentTime time.Time, flow models.Flows, db *bun.DB, context context.Context, project models.Projects) (scheduledAt time.Time) {
// calculate the next execution time
var nextExecutionTime time.Time
switch flow.ScheduleEveryUnit {
@@ -119,8 +126,8 @@ func createExecution(currentTime time.Time, flow models.Flows, db *bun.DB, conte
}
// check for encryption
- if flow.EncryptExecutions && step.Messages != nil && len(step.Messages) > 0 {
- step.Messages, err = encryption.EncryptExecutionStepActionMessage(step.Messages)
+ if project.EncryptionEnabled && step.Messages != nil && len(step.Messages) > 0 {
+ step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages. ", err)
return
diff --git a/services/backend/functions/encryption/migration.go b/services/backend/functions/encryption/migration.go
new file mode 100644
index 00000000..31e597ba
--- /dev/null
+++ b/services/backend/functions/encryption/migration.go
@@ -0,0 +1,146 @@
+package encryption
+
+import (
+ "context"
+
+ "github.com/uptrace/bun"
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
+
+ log "github.com/sirupsen/logrus"
+)
+
+// MigrateProjectEncryption migrates all encrypted data in a project from old key to new key
+// This is useful when rotating encryption keys or migrating from global to project-specific encryption
+func MigrateProjectsEncryption(oldKey string, db *bun.DB) error {
+
+ // check if already migrated
+ var settings models.Settings
+ err := db.NewSelect().Model(&settings).Where("id = ?", 1).Scan(context.Background())
+ if err != nil {
+ return err
+ }
+ if settings.NewEncryptionMigrated {
+ if oldKey != "" {
+ log.Info("Projects already migrated, skipping migration. You can remove the old key from the config.")
+ }
+ return nil
+ }
+
+ log.Info("Migrating projects to new encryption algorithm...")
+
+ var projects []models.Projects
+ err = db.NewSelect().Model(&projects).Scan(context.Background())
+ if err != nil {
+ return err
+ }
+
+ for _, project := range projects {
+ err = EnableProjectEncryption(project.ID.String(), db)
+ if err != nil {
+ return err
+ }
+
+ // Get all flows for this project
+ var flows []models.Flows
+ err := db.NewSelect().Model(&flows).Where("project_id = ?", project.ID).Scan(context.Background())
+ if err != nil {
+ return err
+ }
+
+ for _, flow := range flows {
+ // Decrypt with old key and re-encrypt with new key
+ if len(flow.Actions) > 0 {
+ // Temporarily decrypt with old key
+ decryptedActions, err := DecryptParams(flow.Actions, true)
+ if err != nil {
+ continue
+ }
+
+ // Re-encrypt with new encryption
+ encryptedActions, err := EncryptParamsWithProject(decryptedActions, flow.ProjectID, db)
+ if err != nil {
+ return err
+ }
+
+ // Update the flow with re-encrypted data
+ _, err = db.NewUpdate().Model(&flow).Set("actions = ?", encryptedActions).Where("id = ?", flow.ID).Exec(context.Background())
+ if err != nil {
+ return err
+ }
+ }
+
+ // Handle failure pipeline actions
+ for i, pipeline := range flow.FailurePipelines {
+ if len(pipeline.Actions) > 0 {
+ // Temporarily decrypt with old key
+ decryptedActions, err := DecryptParams(pipeline.Actions, true)
+ if err != nil {
+ continue
+ }
+
+ // Re-encrypt with new key
+ encryptedActions, err := EncryptParamsWithProject(decryptedActions, flow.ProjectID, db)
+ if err != nil {
+ return err
+ }
+
+ flow.FailurePipelines[i].Actions = encryptedActions
+ }
+ }
+
+ // Update failure pipelines
+ _, err = db.NewUpdate().Model(&flow).Set("failure_pipelines = ?", flow.FailurePipelines).Where("id = ?", flow.ID).Exec(context.Background())
+ if err != nil {
+ return err
+ }
+
+ // migrate execution step messages
+ var executions []models.Executions
+ err = db.NewSelect().Model(&executions).Where("flow_id = ?", flow.ID).Scan(context.Background())
+ if err != nil {
+ return err
+ }
+
+ for _, execution := range executions {
+ var steps []models.ExecutionSteps
+ err = db.NewSelect().Model(&steps).Where("execution_id = ?", execution.ID).Scan(context.Background())
+ if err != nil {
+ return err
+ }
+
+ for _, step := range steps {
+ // Decrypt with old key and re-encrypt with new key
+ if len(step.Messages) > 0 {
+ // Temporarily decrypt with old key
+ decryptedMessages, err := DecryptExecutionStepActionMessage(step.Messages)
+ if err != nil {
+ continue
+ }
+
+ // Re-encrypt with new encryption
+ encryptedMessages, err := EncryptExecutionStepActionMessageWithProject(decryptedMessages, project.ID.String(), db)
+ if err != nil {
+ return err
+ }
+
+ // Update the step with re-encrypted data
+ _, err = db.NewUpdate().Model(&step).Set("messages = ?", encryptedMessages).Where("id = ?", step.ID).Exec(context.Background())
+ if err != nil {
+ return err
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // set new_encryption_migrated in settings
+ _, err = db.NewUpdate().Model(&models.Settings{}).Set("new_encryption_migrated = ?", true).Where("id = ?", 1).Exec(context.Background())
+ if err != nil {
+ return err
+ }
+
+ log.Info("Projects migrated successfully")
+
+ return nil
+}
diff --git a/services/backend/functions/encryption/old_encryption.go b/services/backend/functions/encryption/old_encryption.go
new file mode 100644
index 00000000..c5f18d6d
--- /dev/null
+++ b/services/backend/functions/encryption/old_encryption.go
@@ -0,0 +1,160 @@
+package encryption
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "encoding/base64"
+ "encoding/hex"
+ "encoding/json"
+ "errors"
+ "fmt"
+
+ "github.com/v1Flows/exFlow/services/backend/config"
+ shared_models "github.com/v1Flows/shared-library/pkg/models"
+)
+
+func DecryptParams(actions []shared_models.Action, decryptPasswords bool) ([]shared_models.Action, error) {
+ block, err := aes.NewCipher([]byte(config.Config.Encryption.Key))
+ if err != nil {
+ return nil, err
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, err
+ }
+
+ for i, action := range actions {
+ for j, param := range action.Params {
+ // Skip decryption if the value is empty
+ if param.Value == "" {
+ continue
+ }
+
+ if param.Type == "password" && !decryptPasswords {
+ continue
+ }
+
+ // Skip decryption if the value is not encrypted
+ if !IsEncrypted(param.Value) {
+ continue
+ }
+
+ // Decode the hex string
+ ciphertext, err := hex.DecodeString(param.Value)
+ if err != nil {
+ return nil, errors.New("failed to decode hex string: " + err.Error())
+ }
+
+ if len(ciphertext) < gcm.NonceSize() {
+ return nil, errors.New("ciphertext too short")
+ }
+
+ // Extract the nonce and ciphertext
+ nonce := ciphertext[:gcm.NonceSize()]
+ ciphertext = ciphertext[gcm.NonceSize():]
+
+ // Decrypt the ciphertext
+ plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
+ if err != nil {
+ return nil, errors.New("failed to decrypt: " + err.Error())
+ }
+
+ // Convert the decrypted JSON value back to the original type
+ var originalValue interface{}
+ if err := json.Unmarshal(plaintext, &originalValue); err != nil {
+ return nil, err
+ }
+
+ param.Value = fmt.Sprintf("%v", originalValue)
+ actions[i].Params[j] = param
+ }
+
+ // if action has an updated action, decrypt the params of the updated action
+ if action.UpdatedAction != nil {
+ for j, param := range action.UpdatedAction.Params {
+ // skip if value is not encrypted
+ if !IsEncrypted(param.Value) {
+ continue
+ }
+
+ // Skip decryption if the value is empty
+ if param.Value == "" {
+ continue
+ }
+
+ if param.Type == "password" && !decryptPasswords {
+ continue
+ }
+
+ // Decode the hex string
+ ciphertext, err := hex.DecodeString(param.Value)
+ if err != nil {
+ return nil, errors.New("failed to decode hex string: " + err.Error())
+ }
+
+ if len(ciphertext) < gcm.NonceSize() {
+ return nil, errors.New("ciphertext too short")
+ }
+
+ // Extract the nonce and ciphertext
+ nonce := ciphertext[:gcm.NonceSize()]
+ ciphertext = ciphertext[gcm.NonceSize():]
+
+ // Decrypt the ciphertext
+ plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
+ if err != nil {
+ return nil, errors.New("failed to decrypt: " + err.Error())
+ }
+
+ // Convert the decrypted JSON value back to the original type
+ var originalValue interface{}
+ if err := json.Unmarshal(plaintext, &originalValue); err != nil {
+ return nil, err
+ }
+
+ param.Value = fmt.Sprintf("%v", originalValue)
+ action.UpdatedAction.Params[j] = param
+ }
+ }
+ }
+
+ return actions, nil
+}
+
+func DecryptExecutionStepActionMessage(encryptedMessage []shared_models.Message) ([]shared_models.Message, error) {
+ block, err := aes.NewCipher([]byte(config.Config.Encryption.Key))
+ if err != nil {
+ return nil, err
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, err
+ }
+
+ for i := range encryptedMessage {
+ for line := range encryptedMessage[i].Lines {
+ encodedCiphertext := encryptedMessage[i].Lines[line].Content
+ ciphertext, err := base64.StdEncoding.DecodeString(encodedCiphertext)
+ if err != nil {
+ return nil, err
+ }
+
+ nonceSize := gcm.NonceSize()
+ if len(ciphertext) < nonceSize {
+ return nil, errors.New("ciphertext too short")
+ }
+
+ nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
+ plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ encryptedMessage[i].Lines[line].Content = string(plaintext)
+ }
+ }
+
+ return encryptedMessage, nil
+}
diff --git a/services/backend/functions/encryption/payload.go b/services/backend/functions/encryption/payload.go
deleted file mode 100644
index 8b31837b..00000000
--- a/services/backend/functions/encryption/payload.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package encryption
-
-import (
- "github.com/v1Flows/exFlow/services/backend/config"
- "crypto/aes"
- "crypto/cipher"
- "crypto/rand"
- "encoding/base64"
- "encoding/json"
- "io"
-)
-
-func EncryptPayload(payload json.RawMessage) (json.RawMessage, error) {
- block, err := aes.NewCipher([]byte(config.Config.Encryption.Key))
- if err != nil {
- return nil, err
- }
-
- plaintext := []byte(payload)
- ciphertext := make([]byte, aes.BlockSize+len(plaintext))
- iv := ciphertext[:aes.BlockSize]
-
- if _, err := io.ReadFull(rand.Reader, iv); err != nil {
- return nil, err
- }
-
- stream := cipher.NewCFBEncrypter(block, iv)
- stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
-
- // Encode the ciphertext as base64 to ensure it can be stored as JSON
- encodedCiphertext := base64.StdEncoding.EncodeToString(ciphertext)
- encryptedPayload, err := json.Marshal(encodedCiphertext)
- if err != nil {
- return nil, err
- }
-
- return json.RawMessage(encryptedPayload), nil
-}
-
-func DecryptPayload(payload json.RawMessage) (json.RawMessage, error) {
- block, err := aes.NewCipher([]byte(config.Config.Encryption.Key))
- if err != nil {
- return nil, err
- }
-
- var encodedCiphertext string
- if err := json.Unmarshal(payload, &encodedCiphertext); err != nil {
- return nil, err
- }
-
- ciphertext, err := base64.StdEncoding.DecodeString(encodedCiphertext)
- if err != nil {
- return nil, err
- }
-
- iv := ciphertext[:aes.BlockSize]
- ciphertext = ciphertext[aes.BlockSize:]
-
- stream := cipher.NewCFBDecrypter(block, iv)
- stream.XORKeyStream(ciphertext, ciphertext)
-
- return json.RawMessage(ciphertext), nil
-}
diff --git a/services/backend/functions/encryption/execution_step_action_message.go b/services/backend/functions/encryption/project_execution_messages.go
similarity index 65%
rename from services/backend/functions/encryption/execution_step_action_message.go
rename to services/backend/functions/encryption/project_execution_messages.go
index 776b0f40..1d1ba952 100644
--- a/services/backend/functions/encryption/execution_step_action_message.go
+++ b/services/backend/functions/encryption/project_execution_messages.go
@@ -8,12 +8,18 @@ import (
"errors"
"io"
- "github.com/v1Flows/exFlow/services/backend/config"
+ "github.com/uptrace/bun"
shared_models "github.com/v1Flows/shared-library/pkg/models"
)
-func EncryptExecutionStepActionMessage(messages []shared_models.Message) ([]shared_models.Message, error) {
- block, err := aes.NewCipher([]byte(config.Config.Encryption.Key))
+// EncryptExecutionStepActionMessageWithProject encrypts execution step messages using project-specific encryption
+func EncryptExecutionStepActionMessageWithProject(messages []shared_models.Message, projectID string, db *bun.DB) ([]shared_models.Message, error) {
+ encryptionKey, err := getEncryptionKey(projectID, db)
+ if err != nil {
+ return nil, err
+ }
+
+ block, err := aes.NewCipher(encryptionKey)
if err != nil {
return nil, err
}
@@ -43,8 +49,14 @@ func EncryptExecutionStepActionMessage(messages []shared_models.Message) ([]shar
return messages, nil
}
-func DecryptExecutionStepActionMessage(encryptedMessage []shared_models.Message) ([]shared_models.Message, error) {
- block, err := aes.NewCipher([]byte(config.Config.Encryption.Key))
+// DecryptExecutionStepActionMessageWithProject decrypts execution step messages using project-specific encryption
+func DecryptExecutionStepActionMessageWithProject(encryptedMessage []shared_models.Message, projectID string, db *bun.DB) ([]shared_models.Message, error) {
+ encryptionKey, err := getEncryptionKey(projectID, db)
+ if err != nil {
+ return nil, err
+ }
+
+ block, err := aes.NewCipher(encryptionKey)
if err != nil {
return nil, err
}
diff --git a/services/backend/functions/encryption/project_keys.go b/services/backend/functions/encryption/project_keys.go
new file mode 100644
index 00000000..e4941009
--- /dev/null
+++ b/services/backend/functions/encryption/project_keys.go
@@ -0,0 +1,148 @@
+package encryption
+
+import (
+ "context"
+ "crypto/rand"
+ "crypto/sha256"
+ "encoding/hex"
+ "errors"
+
+ "golang.org/x/crypto/pbkdf2"
+
+ "github.com/uptrace/bun"
+ "github.com/v1Flows/exFlow/services/backend/config"
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
+)
+
+// GenerateProjectSalt generates a new random salt for a project
+func GenerateProjectSalt() (string, error) {
+ salt := make([]byte, 32) // 256-bit salt
+ _, err := rand.Read(salt)
+ if err != nil {
+ return "", err
+ }
+ return hex.EncodeToString(salt), nil
+}
+
+// DeriveProjectEncryptionKey derives an encryption key from master secret + project salt
+func DeriveProjectEncryptionKey(projectSalt string, masterSecret string) ([]byte, error) {
+ if masterSecret == "" {
+ return nil, errors.New("master secret not configured")
+ }
+
+ saltBytes, err := hex.DecodeString(projectSalt)
+ if err != nil {
+ return nil, err
+ }
+
+ // Use PBKDF2 to derive a 32-byte key from master secret + project salt
+ // 100,000 iterations should be sufficient for this use case
+ key := pbkdf2.Key([]byte(masterSecret), saltBytes, 100000, 32, sha256.New)
+ return key, nil
+}
+
+// GetProjectEncryptionKey retrieves the encryption key for a specific project
+func GetProjectEncryptionKey(projectID string, db *bun.DB) ([]byte, error) {
+ var project models.Projects
+ err := db.NewSelect().Model(&project).Where("id = ?", projectID).Scan(context.Background())
+ if err != nil {
+ return nil, err
+ }
+
+ if !project.EncryptionEnabled {
+ return nil, errors.New("encryption is disabled for this project")
+ }
+
+ if project.EncryptionKey == "" {
+ return nil, errors.New("encryption salt not found for project")
+ }
+
+ // Derive the actual encryption key from master secret + project salt
+ masterSecret := config.Config.Encryption.MasterSecret
+ if masterSecret == "" {
+ // Fall back to legacy key storage if master secret not configured
+ keyBytes, err := hex.DecodeString(project.EncryptionKey)
+ if err != nil {
+ return nil, err
+ }
+ return keyBytes, nil
+ }
+
+ return DeriveProjectEncryptionKey(project.EncryptionKey, masterSecret)
+}
+
+// SetProjectEncryptionSalt sets the encryption salt for a specific project
+func SetProjectEncryptionSalt(projectID string, encryptionSalt string, db *bun.DB) error {
+ _, err := db.NewUpdate().
+ Model((*models.Projects)(nil)).
+ Set("encryption_key = ?, encryption_enabled = ?", encryptionSalt, true).
+ Where("id = ?", projectID).
+ Exec(context.Background())
+
+ return err
+}
+
+// EnableProjectEncryption enables encryption for a project and generates a new salt if one doesn't exist
+func EnableProjectEncryption(projectID string, db *bun.DB) error {
+ var project models.Projects
+ err := db.NewSelect().Model(&project).Where("id = ?", projectID).Scan(context.Background())
+ if err != nil {
+ return err
+ }
+
+ // Generate a new salt if one doesn't exist
+ if project.EncryptionKey == "" {
+ newSalt, err := GenerateProjectSalt()
+ if err != nil {
+ return err
+ }
+
+ _, err = db.NewUpdate().
+ Model((*models.Projects)(nil)).
+ Set("encryption_key = ?, encryption_enabled = ?", newSalt, true).
+ Where("id = ?", projectID).
+ Exec(context.Background())
+
+ return err
+ }
+
+ // Just enable encryption if salt already exists
+ _, err = db.NewUpdate().
+ Model((*models.Projects)(nil)).
+ Set("encryption_enabled = ?", true).
+ Where("id = ?", projectID).
+ Exec(context.Background())
+
+ return err
+}
+
+// DisableProjectEncryption disables encryption for a project (but keeps the salt)
+func DisableProjectEncryption(projectID string, db *bun.DB) error {
+ _, err := db.NewUpdate().
+ Model((*models.Projects)(nil)).
+ Set("encryption_enabled = ?", false).
+ Where("id = ?", projectID).
+ Exec(context.Background())
+
+ return err
+}
+
+// RotateProjectEncryptionKey generates a new encryption salt for a project
+func RotateProjectEncryptionKey(projectID string, db *bun.DB) (string, error) {
+ newSalt, err := GenerateProjectSalt()
+ if err != nil {
+ return "", err
+ }
+
+ _, err = db.NewUpdate().
+ Model((*models.Projects)(nil)).
+ Set("encryption_key = ?", newSalt).
+ Where("id = ?", projectID).
+ Exec(context.Background())
+
+ if err != nil {
+ return "", err
+ }
+
+ return newSalt, nil
+}
diff --git a/services/backend/functions/encryption/params.go b/services/backend/functions/encryption/project_params.go
similarity index 67%
rename from services/backend/functions/encryption/params.go
rename to services/backend/functions/encryption/project_params.go
index 82da8364..877690bb 100644
--- a/services/backend/functions/encryption/params.go
+++ b/services/backend/functions/encryption/project_params.go
@@ -1,6 +1,7 @@
package encryption
import (
+ "context"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
@@ -10,22 +11,61 @@ import (
"fmt"
"io"
+ "github.com/uptrace/bun"
"github.com/v1Flows/exFlow/services/backend/config"
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
shared_models "github.com/v1Flows/shared-library/pkg/models"
)
-func IsEncrypted(value string) bool {
- // Encrypted values should be at least as long as the AES block size
- if len(value) < aes.BlockSize*2 {
- return false
+// getEncryptionKey returns the appropriate encryption key for a project
+// Falls back to global config key if project encryption is disabled or key is missing
+func getEncryptionKey(projectID string, db *bun.DB) ([]byte, error) {
+ if projectID == "" {
+ // Fall back to global config if no project ID provided
+ return []byte(config.Config.Encryption.Key), nil
+ }
+
+ var project models.Projects
+ err := db.NewSelect().Model(&project).Where("id = ?", projectID).Scan(context.Background())
+ if err != nil {
+ // Fall back to global config if project not found
+ return []byte(config.Config.Encryption.Key), nil
+ }
+
+ // Use project-specific encryption if enabled and salt exists
+ if project.EncryptionEnabled && project.EncryptionKey != "" {
+ // Try to derive key from master secret + salt
+ masterSecret := config.Config.Encryption.MasterSecret
+ if masterSecret != "" {
+ keyBytes, err := DeriveProjectEncryptionKey(project.EncryptionKey, masterSecret)
+ if err != nil {
+ // Fall back to global config if key derivation fails
+ return []byte(config.Config.Encryption.Key), nil
+ }
+ return keyBytes, nil
+ }
+
+ // Legacy: treat stored value as actual key (for backward compatibility)
+ keyBytes, err := hex.DecodeString(project.EncryptionKey)
+ if err != nil {
+ // Fall back to global config if key decode fails
+ return []byte(config.Config.Encryption.Key), nil
+ }
+ return keyBytes, nil
}
- _, err := hex.DecodeString(value)
- return err == nil
+ // Fall back to global config
+ return []byte(config.Config.Encryption.Key), nil
}
-func EncryptParams(actions []shared_models.Action) ([]shared_models.Action, error) {
- block, err := aes.NewCipher([]byte(config.Config.Encryption.Key))
+// EncryptParamsWithProject encrypts action params using project-specific encryption
+func EncryptParamsWithProject(actions []shared_models.Action, projectID string, db *bun.DB) ([]shared_models.Action, error) {
+ encryptionKey, err := getEncryptionKey(projectID, db)
+ if err != nil {
+ return nil, err
+ }
+
+ block, err := aes.NewCipher(encryptionKey)
if err != nil {
return nil, err
}
@@ -108,8 +148,14 @@ func EncryptParams(actions []shared_models.Action) ([]shared_models.Action, erro
return actions, nil
}
-func DecryptParams(actions []shared_models.Action, decryptPasswords bool) ([]shared_models.Action, error) {
- block, err := aes.NewCipher([]byte(config.Config.Encryption.Key))
+// DecryptParamsWithProject decrypts action params using project-specific encryption
+func DecryptParamsWithProject(actions []shared_models.Action, projectID string, decryptPasswords bool, db *bun.DB) ([]shared_models.Action, error) {
+ encryptionKey, err := getEncryptionKey(projectID, db)
+ if err != nil {
+ return nil, err
+ }
+
+ block, err := aes.NewCipher(encryptionKey)
if err != nil {
return nil, err
}
@@ -217,8 +263,14 @@ func DecryptParams(actions []shared_models.Action, decryptPasswords bool) ([]sha
return actions, nil
}
-func EncryptParam(param shared_models.Params) (shared_models.Params, error) {
- block, err := aes.NewCipher([]byte(config.Config.Encryption.Key))
+// EncryptParamWithProject encrypts a single param using project-specific encryption
+func EncryptParamWithProject(param shared_models.Params, projectID string, db *bun.DB) (shared_models.Params, error) {
+ encryptionKey, err := getEncryptionKey(projectID, db)
+ if err != nil {
+ return param, err
+ }
+
+ block, err := aes.NewCipher(encryptionKey)
if err != nil {
return param, err
}
@@ -258,8 +310,14 @@ func EncryptParam(param shared_models.Params) (shared_models.Params, error) {
return param, nil
}
-func DecryptString(value string) (string, error) {
- block, err := aes.NewCipher([]byte(config.Config.Encryption.Key))
+// DecryptStringWithProject decrypts a string using project-specific encryption
+func DecryptStringWithProject(value string, projectID string, db *bun.DB) (string, error) {
+ encryptionKey, err := getEncryptionKey(projectID, db)
+ if err != nil {
+ return "", err
+ }
+
+ block, err := aes.NewCipher(encryptionKey)
if err != nil {
return "", err
}
@@ -291,3 +349,14 @@ func DecryptString(value string) (string, error) {
return string(plaintext), nil
}
+
+func IsEncrypted(value string) bool {
+ decoded, err := hex.DecodeString(value)
+ if err != nil {
+ return false
+ }
+
+ // GCM nonce size is 12 bytes for standard GCM
+ nonceSize := 12
+ return len(decoded) > nonceSize
+}
diff --git a/services/backend/go.mod b/services/backend/go.mod
index 34f550d4..ba854fbb 100644
--- a/services/backend/go.mod
+++ b/services/backend/go.mod
@@ -73,6 +73,6 @@ require (
github.com/sirupsen/logrus v1.9.3
github.com/spf13/viper v1.20.1
github.com/uptrace/bun/dialect/pgdialect v1.2.15
- github.com/v1Flows/shared-library v1.0.25
+ github.com/v1Flows/shared-library v1.0.27
golang.org/x/sys v0.35.0 // indirect
)
diff --git a/services/backend/go.sum b/services/backend/go.sum
index 91587d8f..9bac778a 100644
--- a/services/backend/go.sum
+++ b/services/backend/go.sum
@@ -131,8 +131,8 @@ github.com/uptrace/bun/extra/bunotel v1.2.15 h1:6KAvKRpH9BC/7n3eMXVgDYLqghHf2H3F
github.com/uptrace/bun/extra/bunotel v1.2.15/go.mod h1:qnASdcJVuoEE+13N3Gd8XHi5gwCydt2S1TccJnefH2k=
github.com/uptrace/opentelemetry-go-extra/otelsql v0.3.2 h1:ZjUj9BLYf9PEqBn8W/OapxhPjVRdC6CsXTdULHsyk5c=
github.com/uptrace/opentelemetry-go-extra/otelsql v0.3.2/go.mod h1:O8bHQfyinKwTXKkiKNGmLQS7vRsqRxIQTFZpYpHK3IQ=
-github.com/v1Flows/shared-library v1.0.25 h1:Rez0FNvDXdYByx3JAT8/+BXqld2vmvqUz0rPoBxt5UE=
-github.com/v1Flows/shared-library v1.0.25/go.mod h1:UVP6m6Nri6JC3L0xS3wkbqGvfQJ5fsYIJx81Gfj1TFw=
+github.com/v1Flows/shared-library v1.0.27 h1:BQMZ0hgBMhOHMelygi4Rl7XxriAEKveFarWer9SlN0Q=
+github.com/v1Flows/shared-library v1.0.27/go.mod h1:UVP6m6Nri6JC3L0xS3wkbqGvfQJ5fsYIJx81Gfj1TFw=
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
diff --git a/services/backend/handlers/executions/create_step.go b/services/backend/handlers/executions/create_step.go
index b374556e..7304d781 100644
--- a/services/backend/handlers/executions/create_step.go
+++ b/services/backend/handlers/executions/create_step.go
@@ -35,10 +35,17 @@ func CreateStep(context *gin.Context, db *bun.DB) {
httperror.InternalServerError(context, "Error fetching flow data", err)
return
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting project data from db", err)
+ return
+ }
// check for encryption
- if flow.EncryptExecutions && step.Messages != nil && len(step.Messages) > 0 {
- step.Messages, err = encryption.EncryptExecutionStepActionMessage(step.Messages)
+ if project.EncryptionEnabled && step.Messages != nil && len(step.Messages) > 0 {
+ step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
httperror.InternalServerError(context, "Error encrypting execution step action messages", err)
return
diff --git a/services/backend/handlers/executions/get_step.go b/services/backend/handlers/executions/get_step.go
index d876bb20..3ceef6b9 100644
--- a/services/backend/handlers/executions/get_step.go
+++ b/services/backend/handlers/executions/get_step.go
@@ -1,10 +1,11 @@
package executions
import (
+ "net/http"
+
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
- "net/http"
"github.com/gin-gonic/gin"
"github.com/uptrace/bun"
@@ -21,8 +22,24 @@ func GetStep(context *gin.Context, db *bun.DB) {
return
}
+ // get execution data
+ var execution models.Executions
+ err = db.NewSelect().Model(&execution).Where("id = ?", executionID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error fetching execution data", err)
+ return
+ }
+
+ // get flow data
+ var flow models.Flows
+ err = db.NewSelect().Model(&flow).Where("id = ?", execution.FlowID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error fetching flow data", err)
+ return
+ }
+
if step.Encrypted {
- step.Messages, err = encryption.DecryptExecutionStepActionMessage(step.Messages)
+ step.Messages, err = encryption.DecryptExecutionStepActionMessageWithProject(step.Messages, flow.ProjectID, db)
if err != nil {
httperror.InternalServerError(context, "Error decrypting execution step action messages", err)
return
diff --git a/services/backend/handlers/executions/get_steps.go b/services/backend/handlers/executions/get_steps.go
index 894f050f..06909ccc 100644
--- a/services/backend/handlers/executions/get_steps.go
+++ b/services/backend/handlers/executions/get_steps.go
@@ -21,9 +21,25 @@ func GetSteps(context *gin.Context, db *bun.DB) {
return
}
+ // get execution data
+ var execution models.Executions
+ err = db.NewSelect().Model(&execution).Where("id = ?", executionID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error fetching execution data", err)
+ return
+ }
+
+ // get flow data
+ var flow models.Flows
+ err = db.NewSelect().Model(&flow).Where("id = ?", execution.FlowID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error fetching flow data", err)
+ return
+ }
+
for i := range steps {
if steps[i].Encrypted {
- steps[i].Messages, err = encryption.DecryptExecutionStepActionMessage(steps[i].Messages)
+ steps[i].Messages, err = encryption.DecryptExecutionStepActionMessageWithProject(steps[i].Messages, flow.ProjectID, db)
if err != nil {
httperror.InternalServerError(context, "Error decrypting execution step action messages", err)
return
diff --git a/services/backend/handlers/executions/schedule.go b/services/backend/handlers/executions/schedule.go
index c4308999..62853743 100644
--- a/services/backend/handlers/executions/schedule.go
+++ b/services/backend/handlers/executions/schedule.go
@@ -77,9 +77,17 @@ func ScheduleExecution(context *gin.Context, db *bun.DB) {
return
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting project data from db", err)
+ return
+ }
+
// check for encryption
- if flow.EncryptExecutions && step.Messages != nil && len(step.Messages) > 0 {
- step.Messages, err = encryption.EncryptExecutionStepActionMessage(step.Messages)
+ if project.EncryptionEnabled && step.Messages != nil && len(step.Messages) > 0 {
+ step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
httperror.InternalServerError(context, "Error encrypting execution step action messages", err)
return
diff --git a/services/backend/handlers/executions/update_step.go b/services/backend/handlers/executions/update_step.go
index 8cf0e867..486883bb 100644
--- a/services/backend/handlers/executions/update_step.go
+++ b/services/backend/handlers/executions/update_step.go
@@ -48,10 +48,17 @@ func UpdateStep(context *gin.Context, db *bun.DB) {
log.Error("Error fetching flow data", err)
return
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting project data from db", err)
+ return
+ }
// check for ecryption and decrypt if needed
- if flow.EncryptExecutions && dbStep.Messages != nil && len(dbStep.Messages) > 0 {
- dbStep.Messages, err = encryption.DecryptExecutionStepActionMessage(dbStep.Messages)
+ if project.EncryptionEnabled && dbStep.Messages != nil && len(dbStep.Messages) > 0 {
+ dbStep.Messages, err = encryption.DecryptExecutionStepActionMessageWithProject(dbStep.Messages, project.ID.String(), db)
if err != nil {
httperror.InternalServerError(context, "Error decrypting execution step action messages", err)
log.Error("Error decrypting execution step action messages", err)
@@ -71,8 +78,8 @@ func UpdateStep(context *gin.Context, db *bun.DB) {
}
// check for ecryption and encrypt if needed
- if flow.EncryptExecutions && step.Messages != nil && len(step.Messages) > 0 {
- step.Messages, err = encryption.EncryptExecutionStepActionMessage(step.Messages)
+ if project.EncryptionEnabled && step.Messages != nil && len(step.Messages) > 0 {
+ step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
httperror.InternalServerError(context, "Error encrypting execution step action messages", err)
log.Error("Error encrypting execution step action messages", err)
diff --git a/services/backend/handlers/flows/add_actions.go b/services/backend/handlers/flows/add_actions.go
index a79b266d..10b7f8ec 100644
--- a/services/backend/handlers/flows/add_actions.go
+++ b/services/backend/handlers/flows/add_actions.go
@@ -5,7 +5,6 @@ import (
"fmt"
"net/http"
- "github.com/v1Flows/exFlow/services/backend/config"
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
@@ -34,6 +33,14 @@ func AddFlowActions(context *gin.Context, db *bun.DB) {
return
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flowDB.ProjectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting project data from db", err)
+ return
+ }
+
// check if user has access to project
access, err := gatekeeper.CheckUserProjectAccess(flowDB.ProjectID, context, db)
if err != nil {
@@ -57,8 +64,8 @@ func AddFlowActions(context *gin.Context, db *bun.DB) {
}
// encrypt action params
- if config.Config.Encryption.Enabled && flowDB.EncryptActionParams {
- flow.Actions, err = encryption.EncryptParams(flow.Actions)
+ if project.EncryptionEnabled {
+ flow.Actions, err = encryption.EncryptParamsWithProject(flow.Actions, flowDB.ProjectID, db)
if err != nil {
httperror.InternalServerError(context, "Error encrypting action params", err)
fmt.Println(err)
diff --git a/services/backend/handlers/flows/add_failure_pipeline_actions.go b/services/backend/handlers/flows/add_failure_pipeline_actions.go
index c366d4b4..8cddf496 100644
--- a/services/backend/handlers/flows/add_failure_pipeline_actions.go
+++ b/services/backend/handlers/flows/add_failure_pipeline_actions.go
@@ -6,7 +6,6 @@ import (
"net/http"
log "github.com/sirupsen/logrus"
- "github.com/v1Flows/exFlow/services/backend/config"
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
@@ -36,6 +35,14 @@ func AddFlowFailurePipelineActions(context *gin.Context, db *bun.DB) {
return
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flowDB.ProjectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting project data from db", err)
+ return
+ }
+
// check if user has access to project
access, err := gatekeeper.CheckUserProjectAccess(flowDB.ProjectID, context, db)
if err != nil {
@@ -59,8 +66,8 @@ func AddFlowFailurePipelineActions(context *gin.Context, db *bun.DB) {
}
// encrypt action params
- if config.Config.Encryption.Enabled && flowDB.EncryptActionParams {
- failurePipeline.Actions, err = encryption.EncryptParams(failurePipeline.Actions)
+ if project.EncryptionEnabled {
+ failurePipeline.Actions, err = encryption.EncryptParamsWithProject(failurePipeline.Actions, flowDB.ProjectID, db)
if err != nil {
httperror.InternalServerError(context, "Error encrypting failure pipeline action params", err)
fmt.Println(err)
diff --git a/services/backend/handlers/flows/get_flow.go b/services/backend/handlers/flows/get_flow.go
index dccc141d..0b3627f8 100644
--- a/services/backend/handlers/flows/get_flow.go
+++ b/services/backend/handlers/flows/get_flow.go
@@ -4,7 +4,6 @@ import (
"errors"
"net/http"
- "github.com/v1Flows/exFlow/services/backend/config"
"github.com/v1Flows/exFlow/services/backend/functions/auth"
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
@@ -26,6 +25,14 @@ func GetFlow(context *gin.Context, db *bun.DB) {
return
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting project data from db", err)
+ return
+ }
+
// check if user has access to project
access, err := gatekeeper.CheckUserProjectAccess(flow.ProjectID, context, db)
if err != nil {
@@ -52,8 +59,8 @@ func GetFlow(context *gin.Context, db *bun.DB) {
decryptPasswords = true
}
- if config.Config.Encryption.Enabled && flow.EncryptActionParams && len(flow.Actions) > 0 {
- flow.Actions, err = encryption.DecryptParams(flow.Actions, decryptPasswords)
+ if project.EncryptionEnabled && len(flow.Actions) > 0 {
+ flow.Actions, err = encryption.DecryptParamsWithProject(flow.Actions, flow.ProjectID, decryptPasswords, db)
if err != nil {
httperror.InternalServerError(context, "Error decrypting action params", err)
return
@@ -62,7 +69,7 @@ func GetFlow(context *gin.Context, db *bun.DB) {
// decrypt failure pipeline actions
for i, pipeline := range flow.FailurePipelines {
if pipeline.Actions != nil {
- flow.FailurePipelines[i].Actions, err = encryption.DecryptParams(pipeline.Actions, decryptPasswords)
+ flow.FailurePipelines[i].Actions, err = encryption.DecryptParamsWithProject(pipeline.Actions, flow.ProjectID, decryptPasswords, db)
if err != nil {
httperror.InternalServerError(context, "Error decrypting action params", err)
return
diff --git a/services/backend/handlers/flows/get_flows.go b/services/backend/handlers/flows/get_flows.go
index 1829d0b9..8da8d422 100644
--- a/services/backend/handlers/flows/get_flows.go
+++ b/services/backend/handlers/flows/get_flows.go
@@ -3,7 +3,6 @@ package flows
import (
"net/http"
- "github.com/v1Flows/exFlow/services/backend/config"
"github.com/v1Flows/exFlow/services/backend/functions/auth"
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
@@ -43,29 +42,36 @@ func GetFlows(context *gin.Context, db *bun.DB) {
decryptPasswords = true
}
- if config.Config.Encryption.Enabled && len(flows) > 0 {
- for i, flow := range flows {
- if flow.EncryptActionParams && len(flow.Actions) > 0 {
- flow.Actions, err = encryption.DecryptParams(flow.Actions, decryptPasswords)
- if err != nil {
- httperror.InternalServerError(context, "Error decrypting action params", err)
- return
- }
+ for i, flow := range flows {
- flows[i].Actions = flow.Actions
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting project data from db", err)
+ return
+ }
- // decrypt failure pipeline actions
- for i, pipeline := range flow.FailurePipelines {
- if pipeline.Actions != nil {
- flow.FailurePipelines[i].Actions, err = encryption.DecryptParams(pipeline.Actions, decryptPasswords)
- if err != nil {
- httperror.InternalServerError(context, "Error decrypting action params", err)
- return
- }
- }
+ if project.EncryptionEnabled && len(flow.Actions) > 0 {
+ flow.Actions, err = encryption.DecryptParamsWithProject(flow.Actions, flow.ProjectID, decryptPasswords, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error decrypting action params", err)
+ return
+ }
- flows[i].FailurePipelines = flow.FailurePipelines
+ flows[i].Actions = flow.Actions
+
+ // decrypt failure pipeline actions
+ for i, pipeline := range flow.FailurePipelines {
+ if pipeline.Actions != nil {
+ flow.FailurePipelines[i].Actions, err = encryption.DecryptParamsWithProject(pipeline.Actions, flow.ProjectID, decryptPasswords, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error decrypting action params", err)
+ return
+ }
}
+
+ flows[i].FailurePipelines = flow.FailurePipelines
}
}
}
diff --git a/services/backend/handlers/flows/start_execution.go b/services/backend/handlers/flows/start_execution.go
index dea1c8d1..ff41e9d4 100644
--- a/services/backend/handlers/flows/start_execution.go
+++ b/services/backend/handlers/flows/start_execution.go
@@ -27,6 +27,14 @@ func StartExecution(context *gin.Context, db *bun.DB) {
return
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting project data from db", err)
+ return
+ }
+
// check auth token type
tokenType, err := auth.GetTypeFromToken(context.GetHeader("Authorization"))
if err != nil {
@@ -74,8 +82,8 @@ func StartExecution(context *gin.Context, db *bun.DB) {
}
// check for encryption
- if flow.EncryptExecutions && step.Messages != nil && len(step.Messages) > 0 {
- step.Messages, err = encryption.EncryptExecutionStepActionMessage(step.Messages)
+ if project.EncryptionEnabled && step.Messages != nil && len(step.Messages) > 0 {
+ step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
httperror.InternalServerError(context, "Error encrypting execution step action messages", err)
return
diff --git a/services/backend/handlers/flows/update.go b/services/backend/handlers/flows/update.go
index 092d3c08..99e5faf5 100644
--- a/services/backend/handlers/flows/update.go
+++ b/services/backend/handlers/flows/update.go
@@ -71,12 +71,6 @@ func UpdateFlow(context *gin.Context, db *bun.DB) {
if flow.RunnerID != flowDB.RunnerID {
columns = append(columns, "runner_id")
}
- if flow.EncryptActionParams != flowDB.EncryptActionParams {
- columns = append(columns, "encrypt_action_params")
- }
- if flow.EncryptExecutions != flowDB.EncryptExecutions {
- columns = append(columns, "encrypt_executions")
- }
if flow.ScheduleEveryValue != flowDB.ScheduleEveryValue {
columns = append(columns, "schedule_every_value")
}
diff --git a/services/backend/handlers/flows/update_actions.go b/services/backend/handlers/flows/update_actions.go
index 2b8fc67c..719d9ea1 100644
--- a/services/backend/handlers/flows/update_actions.go
+++ b/services/backend/handlers/flows/update_actions.go
@@ -4,7 +4,6 @@ import (
"errors"
"net/http"
- "github.com/v1Flows/exFlow/services/backend/config"
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
@@ -34,6 +33,14 @@ func UpdateFlowActions(context *gin.Context, db *bun.DB) {
return
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flowDB.ProjectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting project data from db", err)
+ return
+ }
+
// check if user has access to project
access, err := gatekeeper.CheckUserProjectAccess(flowDB.ProjectID, context, db)
if err != nil {
@@ -57,8 +64,8 @@ func UpdateFlowActions(context *gin.Context, db *bun.DB) {
}
// encrypt action params
- if config.Config.Encryption.Enabled && flowDB.EncryptActionParams {
- flow.Actions, err = encryption.EncryptParams(flow.Actions)
+ if project.EncryptionEnabled {
+ flow.Actions, err = encryption.EncryptParamsWithProject(flow.Actions, project.ID.String(), db)
if err != nil {
httperror.InternalServerError(context, "Error encrypting action params", err)
return
diff --git a/services/backend/handlers/flows/update_actions_details.go b/services/backend/handlers/flows/update_actions_details.go
index 27106b04..3e77fe70 100644
--- a/services/backend/handlers/flows/update_actions_details.go
+++ b/services/backend/handlers/flows/update_actions_details.go
@@ -4,7 +4,6 @@ import (
"errors"
"net/http"
- "github.com/v1Flows/exFlow/services/backend/config"
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
@@ -34,6 +33,14 @@ func UpdateFlowActionsDetails(context *gin.Context, db *bun.DB) {
return
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flowDB.ProjectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting project data from db", err)
+ return
+ }
+
// check if user has access to project
access, err := gatekeeper.CheckUserProjectAccess(flowDB.ProjectID, context, db)
if err != nil {
@@ -56,23 +63,17 @@ func UpdateFlowActionsDetails(context *gin.Context, db *bun.DB) {
return
}
- if (!flowDB.EncryptActionParams && flow.EncryptActionParams) && config.Config.Encryption.Enabled {
- flow.Actions, err = encryption.EncryptParams(flowDB.Actions)
+ if project.EncryptionEnabled {
+ flow.Actions, err = encryption.EncryptParamsWithProject(flowDB.Actions, flowDB.ProjectID, db)
if err != nil {
httperror.InternalServerError(context, "Error encrypting action params", err)
return
}
- } else if flowDB.EncryptActionParams && !flow.EncryptActionParams && config.Config.Encryption.Enabled {
- flow.Actions, err = encryption.DecryptParams(flowDB.Actions, true)
- if err != nil {
- httperror.InternalServerError(context, "Error decrypting action params", err)
- return
- }
} else {
flow.Actions = flowDB.Actions
}
- _, err = db.NewUpdate().Model(&flow).Column("encrypt_action_params", "exec_parallel", "patterns", "actions").Where("id = ?", flowID).Exec(context)
+ _, err = db.NewUpdate().Model(&flow).Column("exec_parallel", "patterns", "actions").Where("id = ?", flowID).Exec(context)
if err != nil {
httperror.InternalServerError(context, "Error updating actions details on db", err)
return
diff --git a/services/backend/handlers/flows/update_failure_pipeline.go b/services/backend/handlers/flows/update_failure_pipeline.go
index bdff99b4..6a2516ef 100644
--- a/services/backend/handlers/flows/update_failure_pipeline.go
+++ b/services/backend/handlers/flows/update_failure_pipeline.go
@@ -5,7 +5,6 @@ import (
"net/http"
"time"
- "github.com/v1Flows/exFlow/services/backend/config"
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
@@ -35,6 +34,14 @@ func UpdateFlowFailurePipelines(context *gin.Context, db *bun.DB) {
return
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flowDB.ProjectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting project data from db", err)
+ return
+ }
+
// check if user has access to project
access, err := gatekeeper.CheckUserProjectAccess(flow.ProjectID, context, db)
if err != nil {
@@ -60,10 +67,10 @@ func UpdateFlowFailurePipelines(context *gin.Context, db *bun.DB) {
flow.UpdatedAt = time.Now()
// encrypt the actions for each failure pipeline
- if config.Config.Encryption.Enabled && flowDB.EncryptActionParams {
+ if project.EncryptionEnabled {
for i := range flow.FailurePipelines {
if flow.FailurePipelines[i].Actions != nil {
- flow.FailurePipelines[i].Actions, err = encryption.EncryptParams(flow.FailurePipelines[i].Actions)
+ flow.FailurePipelines[i].Actions, err = encryption.EncryptParamsWithProject(flow.FailurePipelines[i].Actions, project.ID.String(), db)
if err != nil {
httperror.InternalServerError(context, "Error encrypting actions", err)
return
diff --git a/services/backend/handlers/flows/update_failure_pipeline_actions.go b/services/backend/handlers/flows/update_failure_pipeline_actions.go
index a3a801f5..979db7fe 100644
--- a/services/backend/handlers/flows/update_failure_pipeline_actions.go
+++ b/services/backend/handlers/flows/update_failure_pipeline_actions.go
@@ -4,7 +4,6 @@ import (
"errors"
"net/http"
- "github.com/v1Flows/exFlow/services/backend/config"
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
@@ -36,6 +35,14 @@ func UpdateFlowFailurePipelineActions(context *gin.Context, db *bun.DB) {
return
}
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flowDB.ProjectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting project data from db", err)
+ return
+ }
+
// check if user has access to project
access, err := gatekeeper.CheckUserProjectAccess(flowDB.ProjectID, context, db)
if err != nil {
@@ -59,8 +66,8 @@ func UpdateFlowFailurePipelineActions(context *gin.Context, db *bun.DB) {
}
// encrypt action params
- if config.Config.Encryption.Enabled && flowDB.EncryptActionParams {
- failurePipeline.Actions, err = encryption.EncryptParams(failurePipeline.Actions)
+ if project.EncryptionEnabled {
+ failurePipeline.Actions, err = encryption.EncryptParamsWithProject(failurePipeline.Actions, project.ID.String(), db)
if err != nil {
httperror.InternalServerError(context, "Error encrypting action params", err)
return
diff --git a/services/backend/handlers/projects/create.go b/services/backend/handlers/projects/create.go
index 1f6d3eea..5dbe27c3 100644
--- a/services/backend/handlers/projects/create.go
+++ b/services/backend/handlers/projects/create.go
@@ -8,6 +8,7 @@ import (
"time"
"github.com/v1Flows/exFlow/services/backend/functions/auth"
+ "github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
functions_runner "github.com/v1Flows/exFlow/services/backend/functions/runner"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
@@ -55,7 +56,16 @@ func CreateProject(context *gin.Context, db *bun.DB) {
return
}
- _, err = db.NewInsert().Model(&project).Column("id", "name", "description", "shared_runners", "icon", "color", "runner_auto_join_token").Exec(context)
+ // Generate encryption salt for the new project
+ encryptionSalt, err := encryption.GenerateProjectSalt()
+ if err != nil {
+ httperror.InternalServerError(context, "Error generating encryption salt", err)
+ return
+ }
+ project.EncryptionKey = encryptionSalt
+ project.EncryptionEnabled = true
+
+ _, err = db.NewInsert().Model(&project).Column("id", "name", "description", "shared_runners", "icon", "color", "runner_auto_join_token", "encryption_key", "encryption_enabled").Exec(context)
if err != nil {
log.Error(err)
httperror.InternalServerError(context, "Error creating project on db", err)
diff --git a/services/backend/handlers/projects/encryption.go b/services/backend/handlers/projects/encryption.go
new file mode 100644
index 00000000..f8ee5a43
--- /dev/null
+++ b/services/backend/handlers/projects/encryption.go
@@ -0,0 +1,152 @@
+package projects
+
+import (
+ "errors"
+ "net/http"
+
+ "github.com/v1Flows/exFlow/services/backend/functions/encryption"
+ "github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
+ "github.com/v1Flows/exFlow/services/backend/functions/httperror"
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
+
+ "github.com/gin-gonic/gin"
+ "github.com/uptrace/bun"
+)
+
+// GetProjectEncryptionStatus returns the encryption status for a project
+func GetProjectEncryptionStatus(context *gin.Context, db *bun.DB) {
+ projectID := context.Param("projectID")
+
+ // check if user has access to project
+ access, err := gatekeeper.CheckUserProjectAccess(projectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking for project access", err)
+ return
+ }
+ if !access {
+ httperror.Unauthorized(context, "You do not have access to this project", errors.New("you do not have access to this project"))
+ return
+ }
+
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", projectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error receiving project data from db", err)
+ return
+ }
+
+ response := gin.H{
+ "encryption_enabled": project.EncryptionEnabled,
+ "has_encryption_salt": project.EncryptionKey != "",
+ }
+
+ context.JSON(http.StatusOK, response)
+}
+
+// EnableProjectEncryption enables encryption for a project
+func EnableProjectEncryption(context *gin.Context, db *bun.DB) {
+ projectID := context.Param("projectID")
+
+ // check if user has access to project
+ access, err := gatekeeper.CheckUserProjectAccess(projectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking for project access", err)
+ return
+ }
+ if !access {
+ httperror.Unauthorized(context, "You do not have access to this project", errors.New("you do not have access to this project"))
+ return
+ }
+
+ // check the requestors role in project (only owners and editors can manage encryption)
+ canModify, err := gatekeeper.CheckRequestUserProjectModifyRole(projectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking your user permissions on project", err)
+ return
+ }
+ if !canModify {
+ httperror.Unauthorized(context, "You are not allowed to make modifications on this project", errors.New("unauthorized"))
+ return
+ }
+
+ err = encryption.EnableProjectEncryption(projectID, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error enabling project encryption", err)
+ return
+ }
+
+ context.JSON(http.StatusOK, gin.H{"result": "success", "message": "Project encryption enabled"})
+}
+
+// DisableProjectEncryption disables encryption for a project
+func DisableProjectEncryption(context *gin.Context, db *bun.DB) {
+ projectID := context.Param("projectID")
+
+ // check if user has access to project
+ access, err := gatekeeper.CheckUserProjectAccess(projectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking for project access", err)
+ return
+ }
+ if !access {
+ httperror.Unauthorized(context, "You do not have access to this project", errors.New("you do not have access to this project"))
+ return
+ }
+
+ // check the requestors role in project (only owners and editors can manage encryption)
+ canModify, err := gatekeeper.CheckRequestUserProjectModifyRole(projectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking your user permissions on project", err)
+ return
+ }
+ if !canModify {
+ httperror.Unauthorized(context, "You are not allowed to make modifications on this project", errors.New("unauthorized"))
+ return
+ }
+
+ err = encryption.DisableProjectEncryption(projectID, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error disabling project encryption", err)
+ return
+ }
+
+ context.JSON(http.StatusOK, gin.H{"result": "success", "message": "Project encryption disabled"})
+}
+
+// RotateProjectEncryptionKey generates a new encryption key for a project
+func RotateProjectEncryptionKey(context *gin.Context, db *bun.DB) {
+ projectID := context.Param("projectID")
+
+ // check if user has access to project
+ access, err := gatekeeper.CheckUserProjectAccess(projectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking for project access", err)
+ return
+ }
+ if !access {
+ httperror.Unauthorized(context, "You do not have access to this project", errors.New("you do not have access to this project"))
+ return
+ }
+
+ // check the requestors role in project (only owners can rotate encryption keys)
+ canModify, err := gatekeeper.CheckRequestUserProjectModifyRole(projectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking your user permissions on project", err)
+ return
+ }
+ if !canModify {
+ httperror.Unauthorized(context, "You are not allowed to make modifications on this project", errors.New("unauthorized"))
+ return
+ }
+
+ _, err = encryption.RotateProjectEncryptionKey(projectID, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error rotating project encryption key", err)
+ return
+ }
+
+ context.JSON(http.StatusOK, gin.H{
+ "result": "success",
+ "message": "Project encryption salt rotated successfully. Existing encrypted data will continue to work with the old salt until re-encrypted.",
+ })
+}
diff --git a/services/backend/main.go b/services/backend/main.go
index 7e64c6ef..3e7a0909 100644
--- a/services/backend/main.go
+++ b/services/backend/main.go
@@ -6,13 +6,14 @@ import (
"github.com/v1Flows/exFlow/services/backend/config"
"github.com/v1Flows/exFlow/services/backend/database"
"github.com/v1Flows/exFlow/services/backend/functions/background_checks"
+ "github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/router"
"github.com/alecthomas/kingpin/v2"
log "github.com/sirupsen/logrus"
)
-const version string = "1.5.2"
+const version string = "2.0.0"
var (
configFile = kingpin.Flag("config", "Config file").Short('c').Default("config.yaml").String()
@@ -21,15 +22,16 @@ var (
func logging(logLevel string) {
logLevel = strings.ToLower(logLevel)
- if logLevel == "info" {
+ switch logLevel {
+ case "info":
log.SetLevel(log.InfoLevel)
- } else if logLevel == "warn" {
+ case "warn":
log.SetLevel(log.WarnLevel)
- } else if logLevel == "error" {
+ case "error":
log.SetLevel(log.ErrorLevel)
- } else if logLevel == "debug" {
+ case "debug":
log.SetLevel(log.DebugLevel)
- } else {
+ default:
log.SetLevel(log.InfoLevel)
}
}
@@ -57,6 +59,11 @@ func main() {
log.Fatal("Failed to connect to the database")
}
+ err = encryption.MigrateProjectsEncryption(cfg.Encryption.Key, db)
+ if err != nil {
+ log.Fatal("Failed to migrate projects: ", err)
+ }
+
go background_checks.Init(db)
router.StartRouter(db, cfg.Port)
}
diff --git a/services/backend/pkg/models/projects.go b/services/backend/pkg/models/projects.go
index c99a3ced..09192d6f 100644
--- a/services/backend/pkg/models/projects.go
+++ b/services/backend/pkg/models/projects.go
@@ -22,6 +22,8 @@ type Projects struct {
EnableAutoRunners bool `bun:"enable_auto_runners,type:bool,default:false" json:"enable_auto_runners"`
DisableRunnerJoin bool `bun:"disable_runner_join,type:bool,default:false" json:"disable_runner_join"`
RunnerAutoJoinToken string `bun:"runner_auto_join_token,type:text,notnull" json:"runner_auto_join_token"`
+ EncryptionKey string `bun:"encryption_key,type:text,default:''" json:"encryption_key"`
+ EncryptionEnabled bool `bun:"encryption_enabled,type:bool,default:true" json:"encryption_enabled"`
}
type ProjectsWithMembers struct {
diff --git a/services/backend/pkg/models/settings.go b/services/backend/pkg/models/settings.go
index f3234cb5..31311ed9 100644
--- a/services/backend/pkg/models/settings.go
+++ b/services/backend/pkg/models/settings.go
@@ -20,4 +20,5 @@ type Settings struct {
AllowSharedRunnerAutoJoin bool `bun:"allow_shared_runner_auto_join,type:bool,default:true" json:"allow_shared_runner_auto_join"`
AllowSharedRunnerJoin bool `bun:"allow_shared_runner_join,type:bool,default:true" json:"allow_shared_runner_join"`
SharedRunnerAutoJoinToken string `bun:"shared_runner_auto_join_token,type:text,default:''" json:"shared_runner_auto_join_token"`
+ NewEncryptionMigrated bool `bun:"new_encryption_migrated,type:bool,default:false" json:"new_encryption_migrated"`
}
diff --git a/services/backend/router/projects.go b/services/backend/router/projects.go
index b04c5ab8..2d9e8197 100644
--- a/services/backend/router/projects.go
+++ b/services/backend/router/projects.go
@@ -80,5 +80,19 @@ func Projects(router *gin.RouterGroup, db *bun.DB) {
project.PUT("/:projectID/transfer_ownership", func(c *gin.Context) {
projects.TransferOwnership(c, db)
})
+
+ // encryption management
+ project.GET("/:projectID/encryption", func(c *gin.Context) {
+ projects.GetProjectEncryptionStatus(c, db)
+ })
+ project.PUT("/:projectID/encryption/enable", func(c *gin.Context) {
+ projects.EnableProjectEncryption(c, db)
+ })
+ project.PUT("/:projectID/encryption/disable", func(c *gin.Context) {
+ projects.DisableProjectEncryption(c, db)
+ })
+ project.PUT("/:projectID/encryption/rotate-key", func(c *gin.Context) {
+ projects.RotateProjectEncryptionKey(c, db)
+ })
}
}
diff --git a/services/frontend/components/projects/project.tsx b/services/frontend/components/projects/project.tsx
index 0d1096b9..bc490c27 100644
--- a/services/frontend/components/projects/project.tsx
+++ b/services/frontend/components/projects/project.tsx
@@ -79,7 +79,7 @@ export default function Project({
)}
-
+
@@ -166,6 +166,25 @@ export default function Project({
+
+
+
+
+
+
+
+
+ {project.encryption_enabled ? (
+
Enabled
+ ) : (
+
Disabled
+ )}
+
Encryption
+
+
+
+
+
From 0c21ca56b01fa83355a34343a07c5c4d7b161579 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Mon, 18 Aug 2025 15:06:40 +0200
Subject: [PATCH 03/45] refactor: Remove encryption settings from flow modals
and related functions
---
ENCRYPTION_SECURITY.md | 15 -----
.../checkForFlowActionUpdates.go | 1 +
.../checkHangingExecutionSteps.go | 7 ++-
.../checkHangingExecutions.go | 11 +++-
.../checkScheduledExecutions.go | 13 +++-
.../components/flows/flow/settings.tsx | 61 -------------------
services/frontend/components/flows/list.tsx | 2 +-
.../frontend/components/modals/flows/copy.tsx | 39 ------------
.../components/modals/flows/create.tsx | 37 -----------
.../frontend/components/modals/flows/edit.tsx | 2 -
.../frontend/lib/fetch/flow/POST/CopyFlow.ts | 4 --
.../lib/fetch/flow/POST/CreateFlow.ts | 4 --
.../frontend/lib/fetch/flow/PUT/UpdateFlow.ts | 4 --
13 files changed, 29 insertions(+), 171 deletions(-)
diff --git a/ENCRYPTION_SECURITY.md b/ENCRYPTION_SECURITY.md
index 34692939..4fda6874 100644
--- a/ENCRYPTION_SECURITY.md
+++ b/ENCRYPTION_SECURITY.md
@@ -31,15 +31,6 @@ encryption:
key: "legacy-key-for-backward-compatibility"
```
-### Option 3: External Key Management (For Enterprise)
-```yaml
-# For advanced setups, integrate with:
-# - AWS KMS
-# - HashiCorp Vault
-# - Azure Key Vault
-# - Google Cloud KMS
-```
-
## Master Secret Requirements
- **Length**: Minimum 32 characters, recommended 64+ characters
@@ -116,10 +107,4 @@ The system maintains backward compatibility:
```go
// Environment variable
masterSecret := os.Getenv("EXFLOW_ENCRYPTION_MASTER_SECRET")
-
-// Or AWS Secrets Manager
-masterSecret := getFromAWSSecretsManager("exflow/encryption/master-secret")
-
-// Or HashiCorp Vault
-masterSecret := getFromVault("secret/exflow/encryption/master-secret")
```
diff --git a/services/backend/functions/background_checks/checkForFlowActionUpdates.go b/services/backend/functions/background_checks/checkForFlowActionUpdates.go
index 1cbba7e6..598b5376 100644
--- a/services/backend/functions/background_checks/checkForFlowActionUpdates.go
+++ b/services/backend/functions/background_checks/checkForFlowActionUpdates.go
@@ -69,6 +69,7 @@ func processFlowsForProject(db *bun.DB, context context.Context, projectID strin
_, err := db.NewUpdate().Model(&updatedFlow).Where("id = ?", updatedFlow.ID).Set("failure_pipelines = ?, actions = ?", updatedFlow.FailurePipelines, updatedFlow.Actions).Exec(context)
if err != nil {
log.Error("Bot: Error updating flow actions. ", err)
+ continue
}
}
}
diff --git a/services/backend/functions/background_checks/checkHangingExecutionSteps.go b/services/backend/functions/background_checks/checkHangingExecutionSteps.go
index a8b69eba..d4d70062 100644
--- a/services/backend/functions/background_checks/checkHangingExecutionSteps.go
+++ b/services/backend/functions/background_checks/checkHangingExecutionSteps.go
@@ -46,7 +46,8 @@ func checkHangingExecutionSteps(db *bun.DB) {
var project models.Projects
err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
if err != nil {
- return
+ log.Error("Bot: Error getting project data for flow ", flow.ID, err)
+ continue
}
// if the execution is finished, let the step fail
@@ -56,6 +57,7 @@ func checkHangingExecutionSteps(db *bun.DB) {
step.Messages, err = encryption.DecryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
+ continue
}
step.Encrypted = true
@@ -79,6 +81,7 @@ func checkHangingExecutionSteps(db *bun.DB) {
step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
+ continue
}
step.Encrypted = true
@@ -87,6 +90,7 @@ func checkHangingExecutionSteps(db *bun.DB) {
_, err := db.NewUpdate().Model(&step).Column("status", "encrypted", "messages", "finished_at").Where("id = ?", step.ID).Exec(context)
if err != nil {
log.Error("Bot: Error updating step", err)
+ continue
}
// set execution status to error if it is not already set
@@ -100,6 +104,7 @@ func checkHangingExecutionSteps(db *bun.DB) {
_, err := db.NewUpdate().Model(&execution).Column("status", "finished_at").Where("id = ?", execution.ID).Exec(context)
if err != nil {
log.Error("Bot: Error updating execution status to error", err)
+ continue
}
}
continue
diff --git a/services/backend/functions/background_checks/checkHangingExecutions.go b/services/backend/functions/background_checks/checkHangingExecutions.go
index e3c94863..8906869b 100644
--- a/services/backend/functions/background_checks/checkHangingExecutions.go
+++ b/services/backend/functions/background_checks/checkHangingExecutions.go
@@ -36,13 +36,15 @@ func checkHangingExecutions(db *bun.DB) {
err = db.NewSelect().Model(&flow).Where("id = ?", execution.FlowID).Scan(context)
if err != nil {
log.Error("Bot: Error getting flow data", err)
+ continue
}
// get project data
var project models.Projects
err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
if err != nil {
- return
+ log.Error("Bot: Error getting project data", err)
+ continue
}
step := shared_models.ExecutionSteps{
@@ -79,6 +81,7 @@ func checkHangingExecutions(db *bun.DB) {
step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
+ continue
}
step.Encrypted = true
@@ -87,17 +90,20 @@ func checkHangingExecutions(db *bun.DB) {
_, err := db.NewInsert().Model(&step).Exec(context)
if err != nil {
log.Error("Bot: Error adding error step", err)
+ continue
}
_, err = db.NewUpdate().Model(&execution).Set("status = 'error'").Set("finished_at = ?", time.Now()).Where("id = ?", execution.ID).Exec(context)
if err != nil {
log.Error("Bot: Error updating execution", err)
+ continue
}
var steps []models.ExecutionSteps
err = db.NewSelect().Model(&steps).Where("execution_id = ?", execution.ID).Scan(context)
if err != nil {
log.Error("Bot: Error getting steps for execution", err)
+ continue
}
// mark all steps as canceled if they are not finished
@@ -114,6 +120,7 @@ func checkHangingExecutions(db *bun.DB) {
step.Messages, err = encryption.DecryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
+ continue
}
step.Encrypted = true
@@ -135,6 +142,7 @@ func checkHangingExecutions(db *bun.DB) {
step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
+ continue
}
step.Encrypted = true
@@ -143,6 +151,7 @@ func checkHangingExecutions(db *bun.DB) {
_, err := db.NewUpdate().Model(&step).Column("status", "encrypted", "messages", "started_at", "finished_at", "canceled_at", "canceled_by").Where("id = ?", step.ID).Exec(context)
if err != nil {
log.Error("Bot: Error updating step", err)
+ continue
}
}
}
diff --git a/services/backend/functions/background_checks/checkScheduledExecutions.go b/services/backend/functions/background_checks/checkScheduledExecutions.go
index b36fe007..10597a16 100644
--- a/services/backend/functions/background_checks/checkScheduledExecutions.go
+++ b/services/backend/functions/background_checks/checkScheduledExecutions.go
@@ -31,13 +31,15 @@ func checkScheduledExecutions(db *bun.DB) {
err = db.NewSelect().Model(&flow).Where("id = ?", execution.FlowID).Scan(context)
if err != nil {
log.Error("Bot: Error getting flow data", err)
+ continue
}
// get project data
var project models.Projects
err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
if err != nil {
- return
+ log.Error("Bot: Error getting project data", err)
+ continue
}
// update the scheduled step to success
@@ -45,6 +47,7 @@ func checkScheduledExecutions(db *bun.DB) {
err = db.NewSelect().Model(&steps).Where("execution_id = ?", execution.ID).Scan(context)
if err != nil {
log.Error("Bot: Error getting steps for execution", err)
+ continue
}
// mark all steps as canceled if they are not finished
@@ -57,7 +60,8 @@ func checkScheduledExecutions(db *bun.DB) {
if project.EncryptionEnabled && step.Messages != nil && len(step.Messages) > 0 {
step.Messages, err = encryption.DecryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
- log.Error("Bot: Error encrypting execution step action messages", err)
+ log.Error("Bot: Error decrypting execution step action messages", err)
+ continue
}
step.Encrypted = true
@@ -79,6 +83,7 @@ func checkScheduledExecutions(db *bun.DB) {
step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
+ continue
}
step.Encrypted = true
@@ -87,6 +92,7 @@ func checkScheduledExecutions(db *bun.DB) {
_, err = db.NewUpdate().Model(&step).Set("status = ?, finished_at = ?, messages = ?", step.Status, step.FinishedAt, step.Messages).Where("id = ?", step.ID).Exec(context)
if err != nil {
log.Error("Bot: Error updating step", err)
+ continue
}
// create execution step which tells that the execution is registerd and waiting for runner to pick it up
@@ -117,6 +123,7 @@ func checkScheduledExecutions(db *bun.DB) {
step.Messages, err = encryption.EncryptExecutionStepActionMessageWithProject(step.Messages, project.ID.String(), db)
if err != nil {
log.Error("Bot: Error encrypting execution step action messages", err)
+ continue
}
step.Encrypted = true
@@ -125,6 +132,7 @@ func checkScheduledExecutions(db *bun.DB) {
_, err = db.NewInsert().Model(&step).Exec(context)
if err != nil {
log.Error("Bot: Error adding error step", err)
+ continue
}
}
}
@@ -132,6 +140,7 @@ func checkScheduledExecutions(db *bun.DB) {
_, err = db.NewUpdate().Model(&execution).Set("status = 'pending'").Where("id = ?", execution.ID).Exec(context)
if err != nil {
log.Error("Bot: Error updating execution", err)
+ continue
}
}
}
diff --git a/services/frontend/components/flows/flow/settings.tsx b/services/frontend/components/flows/flow/settings.tsx
index a2481877..8a37eaf4 100644
--- a/services/frontend/components/flows/flow/settings.tsx
+++ b/services/frontend/components/flows/flow/settings.tsx
@@ -7,7 +7,6 @@ import {
Select,
SelectItem,
Spacer,
- Switch,
} from "@heroui/react";
import { useRouter } from "next/navigation";
import { useState } from "react";
@@ -31,12 +30,6 @@ export default function FlowSettings({
const [failurePipelineID, setFailurePipelineID] = useState(
flow.failure_pipeline_id,
);
- const [encryptExecutions, setEncryptExecutions] = useState(
- flow.encrypt_executions,
- );
- const [encryptActionParams, setEncryptActionParams] = useState(
- flow.encrypt_action_params,
- );
const [scheduleEveryValue, setScheduleEveryValue] = useState(
flow.schedule_every_value,
);
@@ -55,8 +48,6 @@ export default function FlowSettings({
flow.project_id,
flow.folder_id,
flow.runner_id,
- encryptExecutions,
- encryptActionParams,
execParallel,
failurePipelineID,
scheduleEveryValue,
@@ -212,58 +203,6 @@ export default function FlowSettings({
-
-
Encryption
-
-
-
-
-
-
Action Parameters
-
- The parameters of actions will be encrypted stored on the
- db.
-
-
-
{
- setEncryptActionParams(value);
- }}
- />
-
-
-
-
-
-
-
-
-
Executions
-
- All execution action messages will be stored encrypted on
- the db
-
-
-
{
- setEncryptExecutions(value);
- }}
- />
-
-
-
-
-
- {flow.disabled ? "Disabled" : "Active"}
+ {flow.disabled ? "Disabled" : "Enabled"}
diff --git a/services/frontend/components/modals/flows/copy.tsx b/services/frontend/components/modals/flows/copy.tsx
index 6be367bc..fc303134 100644
--- a/services/frontend/components/modals/flows/copy.tsx
+++ b/services/frontend/components/modals/flows/copy.tsx
@@ -49,9 +49,6 @@ export default function CopyFlowModal({
{
title: "Runner",
},
- {
- title: "Encryption",
- },
]);
const [disableNext, setDisableNext] = useState(false);
const [currentStep, setCurrentStep] = useState(0);
@@ -62,8 +59,6 @@ export default function CopyFlowModal({
const [projectId, setProjectId] = useState("");
const [runnerId, setRunnerId] = useState("");
const [runnerLimit, setRunnerLimit] = useState(false);
- const [encryptExecutions, setEncryptExecutions] = useState(true);
- const [encryptActionParameters, setEncryptActionParameters] = useState(true);
// loading
const [isLoading, setIsLoading] = useState(false);
@@ -81,8 +76,6 @@ export default function CopyFlowModal({
setFolderId(flow.folder_id);
setRunnerId(flow.runner_id);
setRunnerLimit(flow.runner_id !== "any");
- setEncryptExecutions(flow.encrypt_executions);
- setEncryptActionParameters(flow.encrypt_action_params);
}
}, [disclosure.isOpen]);
@@ -111,8 +104,6 @@ export default function CopyFlowModal({
folderId,
projectId,
runnerLimit ? runnerId : "any",
- encryptExecutions,
- encryptActionParameters,
flow.actions,
flow.failure_pipelines,
flow.failure_pipeline_id,
@@ -283,36 +274,6 @@ export default function CopyFlowModal({
)}
>
)}
- {currentStep === 2 && (
- <>
-
-
-
Executions
-
- All execution action messages will be stored encrypted
- on the db
-
-
-
-
-
-
-
Action Params
-
- All action parameters will be stored encrypted on the
- db
-
-
-
-
- >
- )}
)}
- {currentStep === 2 && (
- <>
-
-
-
Executions
-
- All execution action messages will be stored encrypted
- on the db
-
-
-
-
-
-
-
Action Params
-
- All action parameters will be stored encrypted on the
- db
-
-
-
-
- >
- )}
{
try {
const cookieStore = await cookies();
@@ -52,8 +50,6 @@ export default async function CreateFlow(
folder_id: folderId,
project_id: projectId,
runner_id: runnerId,
- encrypt_executions: encryptExecutions,
- encrypt_action_params: encryptActionParams,
}),
},
);
diff --git a/services/frontend/lib/fetch/flow/PUT/UpdateFlow.ts b/services/frontend/lib/fetch/flow/PUT/UpdateFlow.ts
index 27a74704..4147d5b8 100644
--- a/services/frontend/lib/fetch/flow/PUT/UpdateFlow.ts
+++ b/services/frontend/lib/fetch/flow/PUT/UpdateFlow.ts
@@ -24,8 +24,6 @@ export default async function UpdateFlow(
projectID: string,
folderID: string,
runnerID: string,
- encryptExecutions: boolean,
- encryptActionParams: boolean,
execParallel: boolean,
failurePipelineID: string,
scheduleEveryValue: number,
@@ -49,8 +47,6 @@ export default async function UpdateFlow(
project_id: projectID,
runner_id: runnerID,
folder_id: folderID,
- encrypt_executions: encryptExecutions,
- encrypt_action_params: encryptActionParams,
exec_parallel: execParallel,
failure_pipeline_id: failurePipelineID,
schedule_every_value: scheduleEveryValue,
From 2915383f6d7c837c52c0dae0f2759b2503de6383 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 19 Aug 2025 06:30:09 +0000
Subject: [PATCH 04/45] chore(deps): bump eslint-config-next in
/services/frontend
Bumps [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) from 15.3.5 to 15.4.7.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v15.4.7/packages/eslint-config-next)
---
updated-dependencies:
- dependency-name: eslint-config-next
dependency-version: 15.4.7
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
services/frontend/package.json | 2 +-
services/frontend/pnpm-lock.yaml | 253 ++++++++++++++++---------------
2 files changed, 135 insertions(+), 120 deletions(-)
diff --git a/services/frontend/package.json b/services/frontend/package.json
index 2f0a7510..9de6ec7b 100644
--- a/services/frontend/package.json
+++ b/services/frontend/package.json
@@ -50,7 +50,7 @@
"cobe": "^0.6.3",
"dotenv": "^16.4.7",
"eslint": "^9.22.0",
- "eslint-config-next": "15.3.5",
+ "eslint-config-next": "15.4.7",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jest-dom": "^5.5.0",
diff --git a/services/frontend/pnpm-lock.yaml b/services/frontend/pnpm-lock.yaml
index 5bf39c2f..7f2f23b9 100644
--- a/services/frontend/pnpm-lock.yaml
+++ b/services/frontend/pnpm-lock.yaml
@@ -129,8 +129,8 @@ importers:
specifier: ^9.22.0
version: 9.22.0(jiti@1.21.7)
eslint-config-next:
- specifier: 15.3.5
- version: 15.3.5(eslint-plugin-import-x@4.10.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ specifier: 15.4.7
+ version: 15.4.7(eslint-plugin-import-x@4.10.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
eslint-config-prettier:
specifier: ^10.1.8
version: 10.1.8(eslint@9.22.0(jiti@1.21.7))
@@ -454,8 +454,8 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
- '@babel/parser@7.28.0':
- resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==}
+ '@babel/parser@7.28.3':
+ resolution: {integrity: sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -975,8 +975,8 @@ packages:
'@emnapi/core@1.4.0':
resolution: {integrity: sha512-H+N/FqT07NmLmt6OFFtDfwe8PNygprzBikrEMyQfgqSmT0vzE515Pz7R8izwB9q/zsH/MA64AKoul3sA6/CzVg==}
- '@emnapi/core@1.4.4':
- resolution: {integrity: sha512-A9CnAbC6ARNMKcIcrQwq6HeHCjpcBZ5wSx4U01WXCqEKlrzB9F9315WDNHkrs2xbx7YjjSxbUYxuN6EQzpcY2g==}
+ '@emnapi/core@1.4.5':
+ resolution: {integrity: sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==}
'@emnapi/runtime@1.4.5':
resolution: {integrity: sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==}
@@ -984,8 +984,8 @@ packages:
'@emnapi/wasi-threads@1.0.1':
resolution: {integrity: sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==}
- '@emnapi/wasi-threads@1.0.3':
- resolution: {integrity: sha512-8K5IFFsQqF9wQNJptGbS6FNKgUTsSRYnTqNCG1vPP8jFdjSv18n2mQfJpkt2Oibo9iBEzcDnDxNwKTzC7svlJw==}
+ '@emnapi/wasi-threads@1.0.4':
+ resolution: {integrity: sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==}
'@es-joy/jsdoccomment@0.49.0':
resolution: {integrity: sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q==}
@@ -2000,8 +2000,8 @@ packages:
'@marijn/find-cluster-break@1.0.2':
resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==}
- '@napi-rs/wasm-runtime@0.2.11':
- resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==}
+ '@napi-rs/wasm-runtime@0.2.12':
+ resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
'@napi-rs/wasm-runtime@0.2.8':
resolution: {integrity: sha512-OBlgKdX7gin7OIq4fadsjpg+cp2ZphvAIKucHsNfTdJiqdOmOEwQd/bHi0VwNrcw5xpBJyUw6cK/QilCqy1BSg==}
@@ -2009,12 +2009,12 @@ packages:
'@next/env@15.3.3':
resolution: {integrity: sha512-OdiMrzCl2Xi0VTjiQQUK0Xh7bJHnOuET2s+3V+Y40WJBAXrJeGA3f+I8MZJ/YQ3mVGi5XGR1L66oFlgqXhQ4Vw==}
- '@next/eslint-plugin-next@15.3.5':
- resolution: {integrity: sha512-BZwWPGfp9po/rAnJcwUBaM+yT/+yTWIkWdyDwc74G9jcfTrNrmsHe+hXHljV066YNdVs8cxROxX5IgMQGX190w==}
-
'@next/eslint-plugin-next@15.4.6':
resolution: {integrity: sha512-2NOu3ln+BTcpnbIDuxx6MNq+pRrCyey4WSXGaJIyt0D2TYicHeO9QrUENNjcf673n3B1s7hsiV5xBYRCK1Q8kA==}
+ '@next/eslint-plugin-next@15.4.7':
+ resolution: {integrity: sha512-asj3RRiEruRLVr+k2ZC4hll9/XBzegMpFMr8IIRpNUYypG86m/a76339X2WETl1C53A512w2INOc2KZV769KPA==}
+
'@next/swc-darwin-arm64@15.3.3':
resolution: {integrity: sha512-WRJERLuH+O3oYB4yZNVahSVFmtxRNjNF1I1c34tYMoJb0Pve+7/RaLAJJizyYiFhjYNGHRAE1Ri2Fd23zgDqhg==}
engines: {node: '>= 10'}
@@ -3263,6 +3263,9 @@ packages:
'@tsparticles/updater-stroke-color@3.8.1':
resolution: {integrity: sha512-rofHCf5oRHP2H+BTJ4D3r4mTqZtre3c8bsdJHATle26+gLpzbt6I1a83wAY8xnsQa1BNnRAfEsnb7GpdZ1vYaw==}
+ '@tybys/wasm-util@0.10.0':
+ resolution: {integrity: sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==}
+
'@tybys/wasm-util@0.9.0':
resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==}
@@ -3545,18 +3548,18 @@ packages:
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
- '@unrs/resolver-binding-android-arm-eabi@1.11.0':
- resolution: {integrity: sha512-LRw5BW29sYj9NsQC6QoqeLVQhEa+BwVINYyMlcve+6stwdBsSt5UB7zw4UZB4+4PNqIVilHoMaPWCb/KhABHQw==}
+ '@unrs/resolver-binding-android-arm-eabi@1.11.1':
+ resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==}
cpu: [arm]
os: [android]
- '@unrs/resolver-binding-android-arm64@1.11.0':
- resolution: {integrity: sha512-zYX8D2zcWCAHqghA8tPjbp7LwjVXbIZP++mpU/Mrf5jUVlk3BWIxkeB8yYzZi5GpFSlqMcRZQxQqbMI0c2lASQ==}
+ '@unrs/resolver-binding-android-arm64@1.11.1':
+ resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==}
cpu: [arm64]
os: [android]
- '@unrs/resolver-binding-darwin-arm64@1.11.0':
- resolution: {integrity: sha512-YsYOT049hevAY/lTYD77GhRs885EXPeAfExG5KenqMJ417nYLS2N/kpRpYbABhFZBVQn+2uRPasTe4ypmYoo3w==}
+ '@unrs/resolver-binding-darwin-arm64@1.11.1':
+ resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==}
cpu: [arm64]
os: [darwin]
@@ -3565,8 +3568,8 @@ packages:
cpu: [arm64]
os: [darwin]
- '@unrs/resolver-binding-darwin-x64@1.11.0':
- resolution: {integrity: sha512-PSjvk3OZf1aZImdGY5xj9ClFG3bC4gnSSYWrt+id0UAv+GwwVldhpMFjAga8SpMo2T1GjV9UKwM+QCsQCQmtdA==}
+ '@unrs/resolver-binding-darwin-x64@1.11.1':
+ resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==}
cpu: [x64]
os: [darwin]
@@ -3575,8 +3578,8 @@ packages:
cpu: [x64]
os: [darwin]
- '@unrs/resolver-binding-freebsd-x64@1.11.0':
- resolution: {integrity: sha512-KC/iFaEN/wsTVYnHClyHh5RSYA9PpuGfqkFua45r4sweXpC0KHZ+BYY7ikfcGPt5w1lMpR1gneFzuqWLQxsRKg==}
+ '@unrs/resolver-binding-freebsd-x64@1.11.1':
+ resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==}
cpu: [x64]
os: [freebsd]
@@ -3585,8 +3588,8 @@ packages:
cpu: [x64]
os: [freebsd]
- '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.0':
- resolution: {integrity: sha512-CDh/0v8uot43cB4yKtDL9CVY8pbPnMV0dHyQCE4lFz6PW/+9tS0i9eqP5a91PAqEBVMqH1ycu+k8rP6wQU846w==}
+ '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1':
+ resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==}
cpu: [arm]
os: [linux]
@@ -3595,8 +3598,8 @@ packages:
cpu: [arm]
os: [linux]
- '@unrs/resolver-binding-linux-arm-musleabihf@1.11.0':
- resolution: {integrity: sha512-+TE7epATDSnvwr3L/hNHX3wQ8KQYB+jSDTdywycg3qDqvavRP8/HX9qdq/rMcnaRDn4EOtallb3vL/5wCWGCkw==}
+ '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1':
+ resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==}
cpu: [arm]
os: [linux]
@@ -3605,8 +3608,8 @@ packages:
cpu: [arm]
os: [linux]
- '@unrs/resolver-binding-linux-arm64-gnu@1.11.0':
- resolution: {integrity: sha512-VBAYGg3VahofpQ+L4k/ZO8TSICIbUKKTaMYOWHWfuYBFqPbSkArZZLezw3xd27fQkxX4BaLGb/RKnW0dH9Y/UA==}
+ '@unrs/resolver-binding-linux-arm64-gnu@1.11.1':
+ resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
cpu: [arm64]
os: [linux]
@@ -3615,8 +3618,8 @@ packages:
cpu: [arm64]
os: [linux]
- '@unrs/resolver-binding-linux-arm64-musl@1.11.0':
- resolution: {integrity: sha512-9IgGFUUb02J1hqdRAHXpZHIeUHRrbnGo6vrRbz0fREH7g+rzQy53/IBSyadZ/LG5iqMxukriNPu4hEMUn+uWEg==}
+ '@unrs/resolver-binding-linux-arm64-musl@1.11.1':
+ resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
cpu: [arm64]
os: [linux]
@@ -3625,8 +3628,8 @@ packages:
cpu: [arm64]
os: [linux]
- '@unrs/resolver-binding-linux-ppc64-gnu@1.11.0':
- resolution: {integrity: sha512-LR4iQ/LPjMfivpL2bQ9kmm3UnTas3U+umcCnq/CV7HAkukVdHxrDD1wwx74MIWbbgzQTLPYY7Ur2MnnvkYJCBQ==}
+ '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
+ resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
cpu: [ppc64]
os: [linux]
@@ -3635,18 +3638,18 @@ packages:
cpu: [ppc64]
os: [linux]
- '@unrs/resolver-binding-linux-riscv64-gnu@1.11.0':
- resolution: {integrity: sha512-HCupFQwMrRhrOg7YHrobbB5ADg0Q8RNiuefqMHVsdhEy9lLyXm/CxsCXeLJdrg27NAPsCaMDtdlm8Z2X8x91Tg==}
+ '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
+ resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
cpu: [riscv64]
os: [linux]
- '@unrs/resolver-binding-linux-riscv64-musl@1.11.0':
- resolution: {integrity: sha512-Ckxy76A5xgjWa4FNrzcKul5qFMWgP5JSQ5YKd0XakmWOddPLSkQT+uAvUpQNnFGNbgKzv90DyQlxPDYPQ4nd6A==}
+ '@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
+ resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
cpu: [riscv64]
os: [linux]
- '@unrs/resolver-binding-linux-s390x-gnu@1.11.0':
- resolution: {integrity: sha512-HfO0PUCCRte2pMJmVyxPI+eqT7KuV3Fnvn2RPvMe5mOzb2BJKf4/Vth8sSt9cerQboMaTVpbxyYjjLBWIuI5BQ==}
+ '@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
+ resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
cpu: [s390x]
os: [linux]
@@ -3655,8 +3658,8 @@ packages:
cpu: [s390x]
os: [linux]
- '@unrs/resolver-binding-linux-x64-gnu@1.11.0':
- resolution: {integrity: sha512-9PZdjP7tLOEjpXHS6+B/RNqtfVUyDEmaViPOuSqcbomLdkJnalt5RKQ1tr2m16+qAufV0aDkfhXtoO7DQos/jg==}
+ '@unrs/resolver-binding-linux-x64-gnu@1.11.1':
+ resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
cpu: [x64]
os: [linux]
@@ -3665,8 +3668,8 @@ packages:
cpu: [x64]
os: [linux]
- '@unrs/resolver-binding-linux-x64-musl@1.11.0':
- resolution: {integrity: sha512-qkE99ieiSKMnFJY/EfyGKVtNra52/k+lVF/PbO4EL5nU6AdvG4XhtJ+WHojAJP7ID9BNIra/yd75EHndewNRfA==}
+ '@unrs/resolver-binding-linux-x64-musl@1.11.1':
+ resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
cpu: [x64]
os: [linux]
@@ -3675,8 +3678,8 @@ packages:
cpu: [x64]
os: [linux]
- '@unrs/resolver-binding-wasm32-wasi@1.11.0':
- resolution: {integrity: sha512-MjXek8UL9tIX34gymvQLecz2hMaQzOlaqYJJBomwm1gsvK2F7hF+YqJJ2tRyBDTv9EZJGMt4KlKkSD/gZWCOiw==}
+ '@unrs/resolver-binding-wasm32-wasi@1.11.1':
+ resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
@@ -3685,8 +3688,8 @@ packages:
engines: {node: '>=14.0.0'}
cpu: [wasm32]
- '@unrs/resolver-binding-win32-arm64-msvc@1.11.0':
- resolution: {integrity: sha512-9LT6zIGO7CHybiQSh7DnQGwFMZvVr0kUjah6qQfkH2ghucxPV6e71sUXJdSM4Ba0MaGE6DC/NwWf7mJmc3DAng==}
+ '@unrs/resolver-binding-win32-arm64-msvc@1.11.1':
+ resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==}
cpu: [arm64]
os: [win32]
@@ -3695,8 +3698,8 @@ packages:
cpu: [arm64]
os: [win32]
- '@unrs/resolver-binding-win32-ia32-msvc@1.11.0':
- resolution: {integrity: sha512-HYchBYOZ7WN266VjoGm20xFv5EonG/ODURRgwl9EZT7Bq1nLEs6VKJddzfFdXEAho0wfFlt8L/xIiE29Pmy1RA==}
+ '@unrs/resolver-binding-win32-ia32-msvc@1.11.1':
+ resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==}
cpu: [ia32]
os: [win32]
@@ -3705,8 +3708,8 @@ packages:
cpu: [ia32]
os: [win32]
- '@unrs/resolver-binding-win32-x64-msvc@1.11.0':
- resolution: {integrity: sha512-+oLKLHw3I1UQo4MeHfoLYF+e6YBa8p5vYUw3Rgt7IDzCs+57vIZqQlIo62NDpYM0VG6BjWOwnzBczMvbtH8hag==}
+ '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
+ resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==}
cpu: [x64]
os: [win32]
@@ -4491,8 +4494,8 @@ packages:
peerDependencies:
eslint: ^9.5.0
- eslint-config-next@15.3.5:
- resolution: {integrity: sha512-oQdvnIgP68wh2RlR3MdQpvaJ94R6qEFl+lnu8ZKxPj5fsAHrSF/HlAOZcsimLw3DT6bnEQIUdbZC2Ab6sWyptg==}
+ eslint-config-next@15.4.7:
+ resolution: {integrity: sha512-tkKKNVJKI4zMIgTpvG2x6mmdhuOdgXUL3AaSPHwxLQkvzi4Yryqvk6B0R5Z4gkpe7FKopz3ZmlpePH3NTHy3gA==}
peerDependencies:
eslint: ^7.23.0 || ^8.0.0 || ^9.0.0
typescript: '>=3.3.1'
@@ -4942,8 +4945,9 @@ packages:
picomatch:
optional: true
- fdir@6.4.6:
- resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==}
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
peerDependencies:
picomatch: ^3 || ^4
peerDependenciesMeta:
@@ -5809,8 +5813,8 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
- napi-postinstall@0.3.0:
- resolution: {integrity: sha512-M7NqKyhODKV1gRLdkwE7pDsZP2/SC2a2vHkOYh9MCpKMbWVfyVfUw5MaH83Fv6XMjxr5jryUp3IDDL9rlxsTeA==}
+ napi-postinstall@0.3.3:
+ resolution: {integrity: sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
hasBin: true
@@ -6022,6 +6026,10 @@ packages:
resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
engines: {node: '>=12'}
+ picomatch@4.0.3:
+ resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
+ engines: {node: '>=12'}
+
pify@2.3.0:
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
engines: {node: '>=0.10.0'}
@@ -6948,8 +6956,8 @@ packages:
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'}
- unrs-resolver@1.11.0:
- resolution: {integrity: sha512-uw3hCGO/RdAEAb4zgJ3C/v6KIAFFOtBoxR86b2Ejc5TnH7HrhTWJR2o0A9ullC3eWMegKQCw/arQ/JivywQzkg==}
+ unrs-resolver@1.11.1:
+ resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==}
unrs-resolver@1.3.3:
resolution: {integrity: sha512-PFLAGQzYlyjniXdbmQ3dnGMZJXX5yrl2YS4DLRfR3BhgUsE1zpRIrccp9XMOGRfIHpdFvCn/nr5N1KMVda4x3A==}
@@ -7460,7 +7468,7 @@ snapshots:
dependencies:
'@babel/types': 7.26.10
- '@babel/parser@7.28.0':
+ '@babel/parser@7.28.3':
dependencies:
'@babel/types': 7.28.2
@@ -8249,9 +8257,9 @@ snapshots:
tslib: 2.8.1
optional: true
- '@emnapi/core@1.4.4':
+ '@emnapi/core@1.4.5':
dependencies:
- '@emnapi/wasi-threads': 1.0.3
+ '@emnapi/wasi-threads': 1.0.4
tslib: 2.8.1
optional: true
@@ -8265,7 +8273,7 @@ snapshots:
tslib: 2.8.1
optional: true
- '@emnapi/wasi-threads@1.0.3':
+ '@emnapi/wasi-threads@1.0.4':
dependencies:
tslib: 2.8.1
optional: true
@@ -9941,11 +9949,11 @@ snapshots:
'@marijn/find-cluster-break@1.0.2': {}
- '@napi-rs/wasm-runtime@0.2.11':
+ '@napi-rs/wasm-runtime@0.2.12':
dependencies:
- '@emnapi/core': 1.4.4
+ '@emnapi/core': 1.4.5
'@emnapi/runtime': 1.4.5
- '@tybys/wasm-util': 0.9.0
+ '@tybys/wasm-util': 0.10.0
optional: true
'@napi-rs/wasm-runtime@0.2.8':
@@ -9957,11 +9965,11 @@ snapshots:
'@next/env@15.3.3': {}
- '@next/eslint-plugin-next@15.3.5':
+ '@next/eslint-plugin-next@15.4.6':
dependencies:
fast-glob: 3.3.1
- '@next/eslint-plugin-next@15.4.6':
+ '@next/eslint-plugin-next@15.4.7':
dependencies:
fast-glob: 3.3.1
@@ -11586,6 +11594,11 @@ snapshots:
dependencies:
'@tsparticles/engine': 3.8.1
+ '@tybys/wasm-util@0.10.0':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
'@tybys/wasm-util@0.9.0':
dependencies:
tslib: 2.8.1
@@ -11955,87 +11968,87 @@ snapshots:
'@ungap/structured-clone@1.3.0': {}
- '@unrs/resolver-binding-android-arm-eabi@1.11.0':
+ '@unrs/resolver-binding-android-arm-eabi@1.11.1':
optional: true
- '@unrs/resolver-binding-android-arm64@1.11.0':
+ '@unrs/resolver-binding-android-arm64@1.11.1':
optional: true
- '@unrs/resolver-binding-darwin-arm64@1.11.0':
+ '@unrs/resolver-binding-darwin-arm64@1.11.1':
optional: true
'@unrs/resolver-binding-darwin-arm64@1.3.3':
optional: true
- '@unrs/resolver-binding-darwin-x64@1.11.0':
+ '@unrs/resolver-binding-darwin-x64@1.11.1':
optional: true
'@unrs/resolver-binding-darwin-x64@1.3.3':
optional: true
- '@unrs/resolver-binding-freebsd-x64@1.11.0':
+ '@unrs/resolver-binding-freebsd-x64@1.11.1':
optional: true
'@unrs/resolver-binding-freebsd-x64@1.3.3':
optional: true
- '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.0':
+ '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1':
optional: true
'@unrs/resolver-binding-linux-arm-gnueabihf@1.3.3':
optional: true
- '@unrs/resolver-binding-linux-arm-musleabihf@1.11.0':
+ '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1':
optional: true
'@unrs/resolver-binding-linux-arm-musleabihf@1.3.3':
optional: true
- '@unrs/resolver-binding-linux-arm64-gnu@1.11.0':
+ '@unrs/resolver-binding-linux-arm64-gnu@1.11.1':
optional: true
'@unrs/resolver-binding-linux-arm64-gnu@1.3.3':
optional: true
- '@unrs/resolver-binding-linux-arm64-musl@1.11.0':
+ '@unrs/resolver-binding-linux-arm64-musl@1.11.1':
optional: true
'@unrs/resolver-binding-linux-arm64-musl@1.3.3':
optional: true
- '@unrs/resolver-binding-linux-ppc64-gnu@1.11.0':
+ '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
optional: true
'@unrs/resolver-binding-linux-ppc64-gnu@1.3.3':
optional: true
- '@unrs/resolver-binding-linux-riscv64-gnu@1.11.0':
+ '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
optional: true
- '@unrs/resolver-binding-linux-riscv64-musl@1.11.0':
+ '@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
optional: true
- '@unrs/resolver-binding-linux-s390x-gnu@1.11.0':
+ '@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
optional: true
'@unrs/resolver-binding-linux-s390x-gnu@1.3.3':
optional: true
- '@unrs/resolver-binding-linux-x64-gnu@1.11.0':
+ '@unrs/resolver-binding-linux-x64-gnu@1.11.1':
optional: true
'@unrs/resolver-binding-linux-x64-gnu@1.3.3':
optional: true
- '@unrs/resolver-binding-linux-x64-musl@1.11.0':
+ '@unrs/resolver-binding-linux-x64-musl@1.11.1':
optional: true
'@unrs/resolver-binding-linux-x64-musl@1.3.3':
optional: true
- '@unrs/resolver-binding-wasm32-wasi@1.11.0':
+ '@unrs/resolver-binding-wasm32-wasi@1.11.1':
dependencies:
- '@napi-rs/wasm-runtime': 0.2.11
+ '@napi-rs/wasm-runtime': 0.2.12
optional: true
'@unrs/resolver-binding-wasm32-wasi@1.3.3':
@@ -12043,19 +12056,19 @@ snapshots:
'@napi-rs/wasm-runtime': 0.2.8
optional: true
- '@unrs/resolver-binding-win32-arm64-msvc@1.11.0':
+ '@unrs/resolver-binding-win32-arm64-msvc@1.11.1':
optional: true
'@unrs/resolver-binding-win32-arm64-msvc@1.3.3':
optional: true
- '@unrs/resolver-binding-win32-ia32-msvc@1.11.0':
+ '@unrs/resolver-binding-win32-ia32-msvc@1.11.1':
optional: true
'@unrs/resolver-binding-win32-ia32-msvc@1.3.3':
optional: true
- '@unrs/resolver-binding-win32-x64-msvc@1.11.0':
+ '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
optional: true
'@unrs/resolver-binding-win32-x64-msvc@1.3.3':
@@ -12070,7 +12083,7 @@ snapshots:
'@vue/compiler-core@3.5.13':
dependencies:
- '@babel/parser': 7.28.0
+ '@babel/parser': 7.28.3
'@vue/shared': 3.5.13
entities: 4.5.0
estree-walker: 2.0.2
@@ -12083,7 +12096,7 @@ snapshots:
'@vue/compiler-sfc@3.5.13':
dependencies:
- '@babel/parser': 7.28.0
+ '@babel/parser': 7.28.3
'@vue/compiler-core': 3.5.13
'@vue/compiler-dom': 3.5.13
'@vue/compiler-ssr': 3.5.13
@@ -12958,9 +12971,9 @@ snapshots:
'@eslint/compat': 1.2.7(eslint@9.22.0(jiti@1.21.7))
eslint: 9.22.0(jiti@1.21.7)
- eslint-config-next@15.3.5(eslint-plugin-import-x@4.10.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3):
+ eslint-config-next@15.4.7(eslint-plugin-import-x@4.10.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3):
dependencies:
- '@next/eslint-plugin-next': 15.3.5
+ '@next/eslint-plugin-next': 15.4.7
'@rushstack/eslint-patch': 1.12.0
'@typescript-eslint/eslint-plugin': 8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
'@typescript-eslint/parser': 8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
@@ -13003,7 +13016,7 @@ snapshots:
is-bun-module: 2.0.0
stable-hash: 0.0.5
tinyglobby: 0.2.14
- unrs-resolver: 1.11.0
+ unrs-resolver: 1.11.1
optionalDependencies:
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.22.0(jiti@1.21.7))
eslint-plugin-import-x: 4.10.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
@@ -13599,9 +13612,9 @@ snapshots:
optionalDependencies:
picomatch: 4.0.2
- fdir@6.4.6(picomatch@4.0.2):
+ fdir@6.5.0(picomatch@4.0.3):
optionalDependencies:
- picomatch: 4.0.2
+ picomatch: 4.0.3
file-entry-cache@8.0.0:
dependencies:
@@ -14739,7 +14752,7 @@ snapshots:
nanoid@3.3.11: {}
- napi-postinstall@0.3.0: {}
+ napi-postinstall@0.3.3: {}
natural-compare@1.4.0: {}
@@ -14964,6 +14977,8 @@ snapshots:
picomatch@4.0.2: {}
+ picomatch@4.0.3: {}
+
pify@2.3.0: {}
pify@4.0.1: {}
@@ -15900,8 +15915,8 @@ snapshots:
tinyglobby@0.2.14:
dependencies:
- fdir: 6.4.6(picomatch@4.0.2)
- picomatch: 4.0.2
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
to-regex-range@5.0.1:
dependencies:
@@ -16050,29 +16065,29 @@ snapshots:
universalify@2.0.1: {}
- unrs-resolver@1.11.0:
+ unrs-resolver@1.11.1:
dependencies:
- napi-postinstall: 0.3.0
+ napi-postinstall: 0.3.3
optionalDependencies:
- '@unrs/resolver-binding-android-arm-eabi': 1.11.0
- '@unrs/resolver-binding-android-arm64': 1.11.0
- '@unrs/resolver-binding-darwin-arm64': 1.11.0
- '@unrs/resolver-binding-darwin-x64': 1.11.0
- '@unrs/resolver-binding-freebsd-x64': 1.11.0
- '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.0
- '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.0
- '@unrs/resolver-binding-linux-arm64-gnu': 1.11.0
- '@unrs/resolver-binding-linux-arm64-musl': 1.11.0
- '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.0
- '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.0
- '@unrs/resolver-binding-linux-riscv64-musl': 1.11.0
- '@unrs/resolver-binding-linux-s390x-gnu': 1.11.0
- '@unrs/resolver-binding-linux-x64-gnu': 1.11.0
- '@unrs/resolver-binding-linux-x64-musl': 1.11.0
- '@unrs/resolver-binding-wasm32-wasi': 1.11.0
- '@unrs/resolver-binding-win32-arm64-msvc': 1.11.0
- '@unrs/resolver-binding-win32-ia32-msvc': 1.11.0
- '@unrs/resolver-binding-win32-x64-msvc': 1.11.0
+ '@unrs/resolver-binding-android-arm-eabi': 1.11.1
+ '@unrs/resolver-binding-android-arm64': 1.11.1
+ '@unrs/resolver-binding-darwin-arm64': 1.11.1
+ '@unrs/resolver-binding-darwin-x64': 1.11.1
+ '@unrs/resolver-binding-freebsd-x64': 1.11.1
+ '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1
+ '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1
+ '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-arm64-musl': 1.11.1
+ '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1
+ '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-x64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-x64-musl': 1.11.1
+ '@unrs/resolver-binding-wasm32-wasi': 1.11.1
+ '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1
+ '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1
+ '@unrs/resolver-binding-win32-x64-msvc': 1.11.1
unrs-resolver@1.3.3:
optionalDependencies:
From 98c9263114c6e66bd5587370a241c17ae8151e57 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Tue, 19 Aug 2025 08:44:12 +0200
Subject: [PATCH 05/45] docs: Update README and docker-compose for encryption
configuration details
---
README.md | 7 ++++---
docker-compose.yaml | 1 +
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 2725a49c..25db4d53 100644
--- a/README.md
+++ b/README.md
@@ -117,9 +117,10 @@ To get started with the exFlow project, follow these steps:
password: postgres
encryption:
- enabled: true
- # maximum 32 characters
- key: null
+ # Minimum 32 characters, recommended 64+ characters
+ master_secret: "your-very-long-and-secure-master-secret-here"
+ # Fallback key for legacy data (optional)
+ key: "legacy-key-for-backward-compatibility"
jwt:
secret: null
diff --git a/docker-compose.yaml b/docker-compose.yaml
index 6a4b0635..a55d98e2 100644
--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -32,6 +32,7 @@ services:
# BACKEND_DATABASE_PASSWORD: postgres
# BACKEND_ENCRYPTION_ENABLED: "true"
# BACKEND_ENCRYPTION_KEY: "change-me"
+ # BACKEND_ENCRYPTION_MASTER_SECRET: "change-me"
# BACKEND_JWT_SECRET: "change-me"
entrypoint: ["/bin/sh", "-c", "until pg_isready -h db -p 5432 -U postgres; do sleep 1; done; exec ./exflow-backend --config /etc/exflow/backend_config.yaml & exec node /app/server.js"]
From 8414bee3101937450a13da3b8c8dda73a8533317 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 19 Aug 2025 06:45:06 +0000
Subject: [PATCH 06/45] chore(deps): bump @radix-ui/react-popover in
/services/frontend
Bumps [@radix-ui/react-popover](https://github.com/radix-ui/primitives) from 1.1.13 to 1.1.15.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/release-process.md)
- [Commits](https://github.com/radix-ui/primitives/commits)
---
updated-dependencies:
- dependency-name: "@radix-ui/react-popover"
dependency-version: 1.1.15
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
services/frontend/package.json | 2 +-
services/frontend/pnpm-lock.yaml | 190 +++++++++++++++----------------
2 files changed, 96 insertions(+), 96 deletions(-)
diff --git a/services/frontend/package.json b/services/frontend/package.json
index 2f0a7510..020e97e1 100644
--- a/services/frontend/package.json
+++ b/services/frontend/package.json
@@ -26,7 +26,7 @@
"@iconify/react": "^6.0.0",
"@internationalized/date": "^3.8.0",
"@number-flow/react": "^0.5.7",
- "@radix-ui/react-popover": "^1.1.13",
+ "@radix-ui/react-popover": "^1.1.15",
"@react-aria/i18n": "^3.12.7",
"@react-aria/ssr": "3.9.8",
"@react-aria/utils": "^3.28.1",
diff --git a/services/frontend/pnpm-lock.yaml b/services/frontend/pnpm-lock.yaml
index 5bf39c2f..f345c951 100644
--- a/services/frontend/pnpm-lock.yaml
+++ b/services/frontend/pnpm-lock.yaml
@@ -57,8 +57,8 @@ importers:
specifier: ^0.5.7
version: 0.5.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-popover':
- specifier: ^1.1.13
- version: 1.1.13(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ specifier: ^1.1.15
+ version: 1.1.15(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/i18n':
specifier: ^3.12.7
version: 3.12.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
@@ -454,8 +454,8 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
- '@babel/parser@7.28.0':
- resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==}
+ '@babel/parser@7.28.3':
+ resolution: {integrity: sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -1108,20 +1108,20 @@ packages:
resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@floating-ui/core@1.7.0':
- resolution: {integrity: sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==}
+ '@floating-ui/core@1.7.3':
+ resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==}
- '@floating-ui/dom@1.7.0':
- resolution: {integrity: sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==}
+ '@floating-ui/dom@1.7.3':
+ resolution: {integrity: sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==}
- '@floating-ui/react-dom@2.1.2':
- resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==}
+ '@floating-ui/react-dom@2.1.5':
+ resolution: {integrity: sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q==}
peerDependencies:
react: '>=16.8.0'
react-dom: '>=16.8.0'
- '@floating-ui/utils@0.2.9':
- resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==}
+ '@floating-ui/utils@0.2.10':
+ resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
'@formatjs/ecma402-abstract@2.3.4':
resolution: {integrity: sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA==}
@@ -2100,11 +2100,11 @@ packages:
'@radix-ui/primitive@1.1.1':
resolution: {integrity: sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==}
- '@radix-ui/primitive@1.1.2':
- resolution: {integrity: sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==}
+ '@radix-ui/primitive@1.1.3':
+ resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==}
- '@radix-ui/react-arrow@1.1.6':
- resolution: {integrity: sha512-2JMfHJf/eVnwq+2dewT3C0acmCWD3XiVA1Da+jTDqo342UlU13WvXtqHhG+yJw5JeQmu4ue2eMy6gcEArLBlcw==}
+ '@radix-ui/react-arrow@1.1.7':
+ resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
@@ -2165,8 +2165,8 @@ packages:
'@types/react-dom':
optional: true
- '@radix-ui/react-dismissable-layer@1.1.5':
- resolution: {integrity: sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==}
+ '@radix-ui/react-dismissable-layer@1.1.11':
+ resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
@@ -2178,8 +2178,8 @@ packages:
'@types/react-dom':
optional: true
- '@radix-ui/react-dismissable-layer@1.1.9':
- resolution: {integrity: sha512-way197PiTvNp+WBP7svMJasHl+vibhWGQDb6Mgf5mhEWJkgb85z7Lfl9TUdkqpWsf8GRNmoopx9ZxCyDzmgRMQ==}
+ '@radix-ui/react-dismissable-layer@1.1.5':
+ resolution: {integrity: sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
@@ -2200,8 +2200,8 @@ packages:
'@types/react':
optional: true
- '@radix-ui/react-focus-guards@1.1.2':
- resolution: {integrity: sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==}
+ '@radix-ui/react-focus-guards@1.1.3':
+ resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
@@ -2222,8 +2222,8 @@ packages:
'@types/react-dom':
optional: true
- '@radix-ui/react-focus-scope@1.1.6':
- resolution: {integrity: sha512-r9zpYNUQY+2jWHWZGyddQLL9YHkM/XvSFHVcWs7bdVuxMAnCwTAuy6Pf47Z4nw7dYcUou1vg/VgjjrrH03VeBw==}
+ '@radix-ui/react-focus-scope@1.1.7':
+ resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
@@ -2253,8 +2253,8 @@ packages:
'@types/react':
optional: true
- '@radix-ui/react-popover@1.1.13':
- resolution: {integrity: sha512-84uqQV3omKDR076izYgcha6gdpN8m3z6w/AeJ83MSBJYVG/AbOHdLjAgsPZkeC/kt+k64moXFCnio8BbqXszlw==}
+ '@radix-ui/react-popover@1.1.15':
+ resolution: {integrity: sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
@@ -2266,8 +2266,8 @@ packages:
'@types/react-dom':
optional: true
- '@radix-ui/react-popper@1.2.6':
- resolution: {integrity: sha512-7iqXaOWIjDBfIG7aq8CUEeCSsQMLFdn7VEE8TaFz704DtEzpPHR7w/uuzRflvKgltqSAImgcmxQ7fFX3X7wasg==}
+ '@radix-ui/react-popper@1.2.8':
+ resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
@@ -2292,8 +2292,8 @@ packages:
'@types/react-dom':
optional: true
- '@radix-ui/react-portal@1.1.8':
- resolution: {integrity: sha512-hQsTUIn7p7fxCPvao/q6wpbxmCwgLrlz+nOrJgC+RwfZqWY/WN+UMqkXzrtKbPrF82P43eCTl3ekeKuyAQbFeg==}
+ '@radix-ui/react-portal@1.1.9':
+ resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
@@ -2318,8 +2318,8 @@ packages:
'@types/react-dom':
optional: true
- '@radix-ui/react-presence@1.1.4':
- resolution: {integrity: sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==}
+ '@radix-ui/react-presence@1.1.5':
+ resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
@@ -2344,8 +2344,8 @@ packages:
'@types/react-dom':
optional: true
- '@radix-ui/react-primitive@2.1.2':
- resolution: {integrity: sha512-uHa+l/lKfxuDD2zjN/0peM/RhhSmRjr5YWdk/37EnSv1nJ88uvG85DPexSm8HdFQROd2VdERJ6ynXbkCFi+APw==}
+ '@radix-ui/react-primitive@2.1.3':
+ resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
@@ -2366,8 +2366,8 @@ packages:
'@types/react':
optional: true
- '@radix-ui/react-slot@1.2.2':
- resolution: {integrity: sha512-y7TBO4xN4Y94FvcWIOIh18fM4R1A8S4q1jhoz4PNzOoHsFcN8pogcFmZrTYAm4F9VRUrWP/Mw7xSKybIeRI+CQ==}
+ '@radix-ui/react-slot@1.2.3':
+ resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
@@ -3870,8 +3870,8 @@ packages:
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
- aria-hidden@1.2.4:
- resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==}
+ aria-hidden@1.2.6:
+ resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==}
engines: {node: '>=10'}
aria-query@5.3.2:
@@ -6196,8 +6196,8 @@ packages:
'@types/react':
optional: true
- react-remove-scroll@2.6.3:
- resolution: {integrity: sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==}
+ react-remove-scroll@2.7.1:
+ resolution: {integrity: sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==}
engines: {node: '>=10'}
peerDependencies:
'@types/react': '*'
@@ -7460,7 +7460,7 @@ snapshots:
dependencies:
'@babel/types': 7.26.10
- '@babel/parser@7.28.0':
+ '@babel/parser@7.28.3':
dependencies:
'@babel/types': 7.28.2
@@ -8462,22 +8462,22 @@ snapshots:
'@eslint/core': 0.13.0
levn: 0.4.1
- '@floating-ui/core@1.7.0':
+ '@floating-ui/core@1.7.3':
dependencies:
- '@floating-ui/utils': 0.2.9
+ '@floating-ui/utils': 0.2.10
- '@floating-ui/dom@1.7.0':
+ '@floating-ui/dom@1.7.3':
dependencies:
- '@floating-ui/core': 1.7.0
- '@floating-ui/utils': 0.2.9
+ '@floating-ui/core': 1.7.3
+ '@floating-ui/utils': 0.2.10
- '@floating-ui/react-dom@2.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@floating-ui/react-dom@2.1.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@floating-ui/dom': 1.7.0
+ '@floating-ui/dom': 1.7.3
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@floating-ui/utils@0.2.9': {}
+ '@floating-ui/utils@0.2.10': {}
'@formatjs/ecma402-abstract@2.3.4':
dependencies:
@@ -10019,11 +10019,11 @@ snapshots:
'@radix-ui/primitive@1.1.1': {}
- '@radix-ui/primitive@1.1.2': {}
+ '@radix-ui/primitive@1.1.3': {}
- '@radix-ui/react-arrow@1.1.6(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
@@ -10068,34 +10068,34 @@ snapshots:
'@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-slot': 1.1.2(@types/react@19.0.12)(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.12)(react@19.0.0)
- aria-hidden: 1.2.4
+ aria-hidden: 1.2.6
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- react-remove-scroll: 2.6.3(@types/react@19.0.12)(react@19.0.0)
+ react-remove-scroll: 2.7.1(@types/react@19.0.12)(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.12
'@types/react-dom': 19.0.1
- '@radix-ui/react-dismissable-layer@1.1.5(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@radix-ui/primitive': 1.1.1
- '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.12)(react@19.0.0)
- '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.0.12)(react@19.0.0)
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.12)(react@19.0.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.0.12)(react@19.0.0)
+ '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.0.12)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.12
'@types/react-dom': 19.0.1
- '@radix-ui/react-dismissable-layer@1.1.9(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-dismissable-layer@1.1.5(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@radix-ui/primitive': 1.1.2
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.12)(react@19.0.0)
- '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.0.12)(react@19.0.0)
- '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.0.12)(react@19.0.0)
+ '@radix-ui/primitive': 1.1.1
+ '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.12)(react@19.0.0)
+ '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.0.12)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
@@ -10108,7 +10108,7 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.12
- '@radix-ui/react-focus-guards@1.1.2(@types/react@19.0.12)(react@19.0.0)':
+ '@radix-ui/react-focus-guards@1.1.3(@types/react@19.0.12)(react@19.0.0)':
dependencies:
react: 19.0.0
optionalDependencies:
@@ -10125,10 +10125,10 @@ snapshots:
'@types/react': 19.0.12
'@types/react-dom': 19.0.1
- '@radix-ui/react-focus-scope@1.1.6(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.12)(react@19.0.0)
- '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.0.12)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -10150,36 +10150,36 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.12
- '@radix-ui/react-popover@1.1.13(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-popover@1.1.15(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@radix-ui/primitive': 1.1.2
+ '@radix-ui/primitive': 1.1.3
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.12)(react@19.0.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.0.12)(react@19.0.0)
- '@radix-ui/react-dismissable-layer': 1.1.9(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-focus-guards': 1.1.2(@types/react@19.0.12)(react@19.0.0)
- '@radix-ui/react-focus-scope': 1.1.6(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.0.12)(react@19.0.0)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-id': 1.1.1(@types/react@19.0.12)(react@19.0.0)
- '@radix-ui/react-popper': 1.2.6(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-portal': 1.1.8(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-slot': 1.2.2(@types/react@19.0.12)(react@19.0.0)
+ '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-slot': 1.2.3(@types/react@19.0.12)(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.0.12)(react@19.0.0)
- aria-hidden: 1.2.4
+ aria-hidden: 1.2.6
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- react-remove-scroll: 2.6.3(@types/react@19.0.12)(react@19.0.0)
+ react-remove-scroll: 2.7.1(@types/react@19.0.12)(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.12
'@types/react-dom': 19.0.1
- '@radix-ui/react-popper@1.2.6(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-popper@1.2.8(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@floating-ui/react-dom': 2.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-arrow': 1.1.6(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@floating-ui/react-dom': 2.1.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.12)(react@19.0.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.0.12)(react@19.0.0)
- '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.0.12)(react@19.0.0)
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.0.12)(react@19.0.0)
'@radix-ui/react-use-rect': 1.1.1(@types/react@19.0.12)(react@19.0.0)
@@ -10201,9 +10201,9 @@ snapshots:
'@types/react': 19.0.12
'@types/react-dom': 19.0.1
- '@radix-ui/react-portal@1.1.8(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-portal@1.1.9(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.0.12)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -10221,7 +10221,7 @@ snapshots:
'@types/react': 19.0.12
'@types/react-dom': 19.0.1
- '@radix-ui/react-presence@1.1.4(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-presence@1.1.5(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.12)(react@19.0.0)
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.0.12)(react@19.0.0)
@@ -10240,9 +10240,9 @@ snapshots:
'@types/react': 19.0.12
'@types/react-dom': 19.0.1
- '@radix-ui/react-primitive@2.1.2(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.0.1)(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@radix-ui/react-slot': 1.2.2(@types/react@19.0.12)(react@19.0.0)
+ '@radix-ui/react-slot': 1.2.3(@types/react@19.0.12)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
@@ -10256,7 +10256,7 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.12
- '@radix-ui/react-slot@1.2.2(@types/react@19.0.12)(react@19.0.0)':
+ '@radix-ui/react-slot@1.2.3(@types/react@19.0.12)(react@19.0.0)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.0.12)(react@19.0.0)
react: 19.0.0
@@ -12070,7 +12070,7 @@ snapshots:
'@vue/compiler-core@3.5.13':
dependencies:
- '@babel/parser': 7.28.0
+ '@babel/parser': 7.28.3
'@vue/shared': 3.5.13
entities: 4.5.0
estree-walker: 2.0.2
@@ -12083,7 +12083,7 @@ snapshots:
'@vue/compiler-sfc@3.5.13':
dependencies:
- '@babel/parser': 7.28.0
+ '@babel/parser': 7.28.3
'@vue/compiler-core': 3.5.13
'@vue/compiler-dom': 3.5.13
'@vue/compiler-ssr': 3.5.13
@@ -12240,7 +12240,7 @@ snapshots:
argparse@2.0.1: {}
- aria-hidden@1.2.4:
+ aria-hidden@1.2.6:
dependencies:
tslib: 2.8.1
@@ -15125,7 +15125,7 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.12
- react-remove-scroll@2.6.3(@types/react@19.0.12)(react@19.0.0):
+ react-remove-scroll@2.7.1(@types/react@19.0.12)(react@19.0.0):
dependencies:
react: 19.0.0
react-remove-scroll-bar: 2.3.8(@types/react@19.0.12)(react@19.0.0)
From 55443f8ec087651b7238a6c16d3153b1071b7229 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 19 Aug 2025 06:52:13 +0000
Subject: [PATCH 07/45] chore(deps): bump eslint-plugin-unused-imports in
/services/frontend
Bumps [eslint-plugin-unused-imports](https://github.com/sweepline/eslint-plugin-unused-imports) from 4.1.4 to 4.2.0.
- [Commits](https://github.com/sweepline/eslint-plugin-unused-imports/compare/v4.1.4...v4.2.0)
---
updated-dependencies:
- dependency-name: eslint-plugin-unused-imports
dependency-version: 4.2.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
services/frontend/package.json | 2 +-
services/frontend/pnpm-lock.yaml | 22 +++++++++++-----------
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/services/frontend/package.json b/services/frontend/package.json
index 2f0a7510..eb07c45b 100644
--- a/services/frontend/package.json
+++ b/services/frontend/package.json
@@ -63,7 +63,7 @@
"eslint-plugin-react-refresh": "^0.4.20",
"eslint-plugin-tailwindcss": "^3.18.2",
"eslint-plugin-testing-library": "^7.1.1",
- "eslint-plugin-unused-imports": "^4.1.4",
+ "eslint-plugin-unused-imports": "^4.2.0",
"framer-motion": "^12.5.0",
"globals": "^15.15.0",
"intl-messageformat": "^10.7.16",
diff --git a/services/frontend/pnpm-lock.yaml b/services/frontend/pnpm-lock.yaml
index 5bf39c2f..9c2bf6cf 100644
--- a/services/frontend/pnpm-lock.yaml
+++ b/services/frontend/pnpm-lock.yaml
@@ -168,8 +168,8 @@ importers:
specifier: ^7.1.1
version: 7.1.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
eslint-plugin-unused-imports:
- specifier: ^4.1.4
- version: 4.1.4(@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))
+ specifier: ^4.2.0
+ version: 4.2.0(@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))
framer-motion:
specifier: ^12.5.0
version: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
@@ -454,8 +454,8 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
- '@babel/parser@7.28.0':
- resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==}
+ '@babel/parser@7.28.3':
+ resolution: {integrity: sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -4785,8 +4785,8 @@ packages:
peerDependencies:
eslint: '>=9.20.0'
- eslint-plugin-unused-imports@4.1.4:
- resolution: {integrity: sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ==}
+ eslint-plugin-unused-imports@4.2.0:
+ resolution: {integrity: sha512-hLbJ2/wnjKq4kGA9AUaExVFIbNzyxYdVo49QZmKCnhk5pc9wcYRbfgLHvWJ8tnsdcseGhoUAddm9gn/lt+d74w==}
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
@@ -7265,7 +7265,7 @@ snapshots:
eslint-plugin-regexp: 2.7.0(eslint@9.22.0(jiti@1.21.7))
eslint-plugin-toml: 0.12.0(eslint@9.22.0(jiti@1.21.7))
eslint-plugin-unicorn: 57.0.0(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-unused-imports: 4.1.4(@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))
+ eslint-plugin-unused-imports: 4.2.0(@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))
eslint-plugin-vue: 10.0.0(eslint@9.22.0(jiti@1.21.7))(vue-eslint-parser@10.1.2(eslint@9.22.0(jiti@1.21.7)))
eslint-plugin-yml: 1.17.0(eslint@9.22.0(jiti@1.21.7))
eslint-processor-vue-blocks: 2.0.0(@vue/compiler-sfc@3.5.13)(eslint@9.22.0(jiti@1.21.7))
@@ -7460,7 +7460,7 @@ snapshots:
dependencies:
'@babel/types': 7.26.10
- '@babel/parser@7.28.0':
+ '@babel/parser@7.28.3':
dependencies:
'@babel/types': 7.28.2
@@ -12070,7 +12070,7 @@ snapshots:
'@vue/compiler-core@3.5.13':
dependencies:
- '@babel/parser': 7.28.0
+ '@babel/parser': 7.28.3
'@vue/shared': 3.5.13
entities: 4.5.0
estree-walker: 2.0.2
@@ -12083,7 +12083,7 @@ snapshots:
'@vue/compiler-sfc@3.5.13':
dependencies:
- '@babel/parser': 7.28.0
+ '@babel/parser': 7.28.3
'@vue/compiler-core': 3.5.13
'@vue/compiler-dom': 3.5.13
'@vue/compiler-ssr': 3.5.13
@@ -13424,7 +13424,7 @@ snapshots:
semver: 7.7.2
strip-indent: 4.0.0
- eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-unused-imports@4.2.0(@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7)):
dependencies:
eslint: 9.22.0(jiti@1.21.7)
optionalDependencies:
From 8dc1dbc767a7ffc8890a725cd7ccd1e108712e35 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 19 Aug 2025 06:52:21 +0000
Subject: [PATCH 08/45] chore(deps): bump the backend group in
/services/backend with 2 updates
Bumps the backend group in /services/backend with 2 updates: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) and [github.com/v1Flows/shared-library](https://github.com/v1Flows/shared-library).
Updates `github.com/mattn/go-sqlite3` from 1.14.31 to 1.14.32
- [Release notes](https://github.com/mattn/go-sqlite3/releases)
- [Commits](https://github.com/mattn/go-sqlite3/compare/v1.14.31...v1.14.32)
Updates `github.com/v1Flows/shared-library` from 1.0.25 to 1.0.27
- [Commits](https://github.com/v1Flows/shared-library/compare/v1.0.25...v1.0.27)
---
updated-dependencies:
- dependency-name: github.com/mattn/go-sqlite3
dependency-version: 1.14.32
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: backend
- dependency-name: github.com/v1Flows/shared-library
dependency-version: 1.0.27
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: backend
...
Signed-off-by: dependabot[bot]
---
services/backend/go.mod | 4 ++--
services/backend/go.sum | 8 ++++----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/services/backend/go.mod b/services/backend/go.mod
index 34f550d4..2e50c958 100644
--- a/services/backend/go.mod
+++ b/services/backend/go.mod
@@ -68,11 +68,11 @@ require (
github.com/golang-jwt/jwt/v5 v5.3.0
github.com/google/uuid v1.6.0
github.com/lib/pq v1.10.9
- github.com/mattn/go-sqlite3 v1.14.31
+ github.com/mattn/go-sqlite3 v1.14.32
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/sirupsen/logrus v1.9.3
github.com/spf13/viper v1.20.1
github.com/uptrace/bun/dialect/pgdialect v1.2.15
- github.com/v1Flows/shared-library v1.0.25
+ github.com/v1Flows/shared-library v1.0.27
golang.org/x/sys v0.35.0 // indirect
)
diff --git a/services/backend/go.sum b/services/backend/go.sum
index 91587d8f..6b410a87 100644
--- a/services/backend/go.sum
+++ b/services/backend/go.sum
@@ -69,8 +69,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/mattn/go-sqlite3 v1.14.31 h1:ldt6ghyPJsokUIlksH63gWZkG6qVGeEAu4zLeS4aVZM=
-github.com/mattn/go-sqlite3 v1.14.31/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
+github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
+github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -131,8 +131,8 @@ github.com/uptrace/bun/extra/bunotel v1.2.15 h1:6KAvKRpH9BC/7n3eMXVgDYLqghHf2H3F
github.com/uptrace/bun/extra/bunotel v1.2.15/go.mod h1:qnASdcJVuoEE+13N3Gd8XHi5gwCydt2S1TccJnefH2k=
github.com/uptrace/opentelemetry-go-extra/otelsql v0.3.2 h1:ZjUj9BLYf9PEqBn8W/OapxhPjVRdC6CsXTdULHsyk5c=
github.com/uptrace/opentelemetry-go-extra/otelsql v0.3.2/go.mod h1:O8bHQfyinKwTXKkiKNGmLQS7vRsqRxIQTFZpYpHK3IQ=
-github.com/v1Flows/shared-library v1.0.25 h1:Rez0FNvDXdYByx3JAT8/+BXqld2vmvqUz0rPoBxt5UE=
-github.com/v1Flows/shared-library v1.0.25/go.mod h1:UVP6m6Nri6JC3L0xS3wkbqGvfQJ5fsYIJx81Gfj1TFw=
+github.com/v1Flows/shared-library v1.0.27 h1:BQMZ0hgBMhOHMelygi4Rl7XxriAEKveFarWer9SlN0Q=
+github.com/v1Flows/shared-library v1.0.27/go.mod h1:UVP6m6Nri6JC3L0xS3wkbqGvfQJ5fsYIJx81Gfj1TFw=
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
From 300f7e6641ca0c11b7d0b3434c00d8c4de22795b Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 19 Aug 2025 07:20:12 +0000
Subject: [PATCH 09/45] chore(deps): bump globals from 15.15.0 to 16.3.0 in
/services/frontend
Bumps [globals](https://github.com/sindresorhus/globals) from 15.15.0 to 16.3.0.
- [Release notes](https://github.com/sindresorhus/globals/releases)
- [Commits](https://github.com/sindresorhus/globals/compare/v15.15.0...v16.3.0)
---
updated-dependencies:
- dependency-name: globals
dependency-version: 16.3.0
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
---
services/frontend/package.json | 2 +-
services/frontend/pnpm-lock.yaml | 22 +++++++++++-----------
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/services/frontend/package.json b/services/frontend/package.json
index 2f0a7510..10317be7 100644
--- a/services/frontend/package.json
+++ b/services/frontend/package.json
@@ -65,7 +65,7 @@
"eslint-plugin-testing-library": "^7.1.1",
"eslint-plugin-unused-imports": "^4.1.4",
"framer-motion": "^12.5.0",
- "globals": "^15.15.0",
+ "globals": "^16.3.0",
"intl-messageformat": "^10.7.16",
"lodash": "^4.17.21",
"lucide-react": "^0.536.0",
diff --git a/services/frontend/pnpm-lock.yaml b/services/frontend/pnpm-lock.yaml
index 5bf39c2f..0edee675 100644
--- a/services/frontend/pnpm-lock.yaml
+++ b/services/frontend/pnpm-lock.yaml
@@ -174,8 +174,8 @@ importers:
specifier: ^12.5.0
version: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
globals:
- specifier: ^15.15.0
- version: 15.15.0
+ specifier: ^16.3.0
+ version: 16.3.0
intl-messageformat:
specifier: ^10.7.16
version: 10.7.16
@@ -454,8 +454,8 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
- '@babel/parser@7.28.0':
- resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==}
+ '@babel/parser@7.28.3':
+ resolution: {integrity: sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -5102,8 +5102,8 @@ packages:
resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==}
engines: {node: '>=18'}
- globals@16.0.0:
- resolution: {integrity: sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==}
+ globals@16.3.0:
+ resolution: {integrity: sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==}
engines: {node: '>=18'}
globalthis@1.0.4:
@@ -7269,7 +7269,7 @@ snapshots:
eslint-plugin-vue: 10.0.0(eslint@9.22.0(jiti@1.21.7))(vue-eslint-parser@10.1.2(eslint@9.22.0(jiti@1.21.7)))
eslint-plugin-yml: 1.17.0(eslint@9.22.0(jiti@1.21.7))
eslint-processor-vue-blocks: 2.0.0(@vue/compiler-sfc@3.5.13)(eslint@9.22.0(jiti@1.21.7))
- globals: 16.0.0
+ globals: 16.3.0
jsonc-eslint-parser: 2.4.0
local-pkg: 1.1.1
parse-gitignore: 2.0.0
@@ -7460,7 +7460,7 @@ snapshots:
dependencies:
'@babel/types': 7.26.10
- '@babel/parser@7.28.0':
+ '@babel/parser@7.28.3':
dependencies:
'@babel/types': 7.28.2
@@ -12070,7 +12070,7 @@ snapshots:
'@vue/compiler-core@3.5.13':
dependencies:
- '@babel/parser': 7.28.0
+ '@babel/parser': 7.28.3
'@vue/shared': 3.5.13
entities: 4.5.0
estree-walker: 2.0.2
@@ -12083,7 +12083,7 @@ snapshots:
'@vue/compiler-sfc@3.5.13':
dependencies:
- '@babel/parser': 7.28.0
+ '@babel/parser': 7.28.3
'@vue/compiler-core': 3.5.13
'@vue/compiler-dom': 3.5.13
'@vue/compiler-ssr': 3.5.13
@@ -13765,7 +13765,7 @@ snapshots:
globals@15.15.0: {}
- globals@16.0.0: {}
+ globals@16.3.0: {}
globalthis@1.0.4:
dependencies:
From bfd260cb7503c05cea796e68056220a7a62f6374 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 19 Aug 2025 08:49:25 +0000
Subject: [PATCH 10/45] chore(deps): bump @react-aria/utils in
/services/frontend
Bumps [@react-aria/utils](https://github.com/adobe/react-spectrum) from 3.28.1 to 3.30.0.
- [Release notes](https://github.com/adobe/react-spectrum/releases)
- [Commits](https://github.com/adobe/react-spectrum/compare/@react-aria/utils@3.28.1...@react-aria/utils@3.30.0)
---
updated-dependencies:
- dependency-name: "@react-aria/utils"
dependency-version: 3.30.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
services/frontend/package.json | 2 +-
services/frontend/pnpm-lock.yaml | 102 ++++++++++++-------------------
2 files changed, 40 insertions(+), 64 deletions(-)
diff --git a/services/frontend/package.json b/services/frontend/package.json
index 2f0a7510..edcb33c3 100644
--- a/services/frontend/package.json
+++ b/services/frontend/package.json
@@ -29,7 +29,7 @@
"@radix-ui/react-popover": "^1.1.13",
"@react-aria/i18n": "^3.12.7",
"@react-aria/ssr": "3.9.8",
- "@react-aria/utils": "^3.28.1",
+ "@react-aria/utils": "^3.30.0",
"@react-aria/visually-hidden": "3.8.26",
"@react-stately/data": "^3.12.3",
"@react-stately/utils": "^3.10.8",
diff --git a/services/frontend/pnpm-lock.yaml b/services/frontend/pnpm-lock.yaml
index 5bf39c2f..222f952b 100644
--- a/services/frontend/pnpm-lock.yaml
+++ b/services/frontend/pnpm-lock.yaml
@@ -66,8 +66,8 @@ importers:
specifier: 3.9.8
version: 3.9.8(react@19.0.0)
'@react-aria/utils':
- specifier: ^3.28.1
- version: 3.28.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ specifier: ^3.30.0
+ version: 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/visually-hidden':
specifier: 3.8.26
version: 3.8.26(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
@@ -454,8 +454,8 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
- '@babel/parser@7.28.0':
- resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==}
+ '@babel/parser@7.28.3':
+ resolution: {integrity: sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -2720,12 +2720,6 @@ packages:
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
- '@react-aria/utils@3.28.1':
- resolution: {integrity: sha512-mnHFF4YOVu9BRFQ1SZSKfPhg3z+lBRYoW5mLcYTQihbKhz48+I1sqRkP7ahMITr8ANH3nb34YaMME4XWmK2Mgg==}
- 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
-
'@react-aria/utils@3.28.2':
resolution: {integrity: sha512-J8CcLbvnQgiBn54eeEvQQbIOfBF3A1QizxMw9P4cl9MkeR03ug7RnjTIdJY/n2p7t59kLeAB3tqiczhcj+Oi5w==}
peerDependencies:
@@ -2780,9 +2774,6 @@ packages:
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/flags@3.1.0':
- resolution: {integrity: sha512-KSHOCxTFpBtxhIRcKwsD1YDTaNxFtCYuAUb0KEihc16QwqZViq4hasgPBs2gYm7fHRbw7WYzWKf6ZSo/+YsFlg==}
-
'@react-stately/flags@3.1.2':
resolution: {integrity: sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==}
@@ -7460,7 +7451,7 @@ snapshots:
dependencies:
'@babel/types': 7.26.10
- '@babel/parser@7.28.0':
+ '@babel/parser@7.28.3':
dependencies:
'@babel/types': 7.28.2
@@ -10345,7 +10336,7 @@ snapshots:
'@react-aria/link': 3.8.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-types/breadcrumbs': 3.7.12(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -10357,7 +10348,7 @@ snapshots:
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-stately/toggle': 3.8.3(react@19.0.0)
'@react-types/button': 3.13.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -10372,7 +10363,7 @@ snapshots:
'@react-stately/calendar': 3.8.0(react@19.0.0)
'@react-types/button': 3.12.0(react@19.0.0)
'@react-types/calendar': 3.7.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -10388,7 +10379,7 @@ snapshots:
'@react-stately/form': 3.1.3(react@19.0.0)
'@react-stately/toggle': 3.8.3(react@19.0.0)
'@react-types/checkbox': 3.9.3(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -10432,7 +10423,7 @@ snapshots:
'@react-types/calendar': 3.7.0(react@19.0.0)
'@react-types/datepicker': 3.12.0(react@19.0.0)
'@react-types/dialog': 3.5.17(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -10473,7 +10464,7 @@ snapshots:
'@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-stately/form': 3.1.3(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -10516,7 +10507,7 @@ snapshots:
'@internationalized/number': 3.6.0
'@internationalized/string': 3.2.5
'@react-aria/ssr': 3.9.8(react@19.0.0)
- '@react-aria/utils': 3.28.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-types/shared': 3.28.0(react@19.0.0)
'@swc/helpers': 0.5.15
react: 19.0.0
@@ -10591,7 +10582,7 @@ snapshots:
'@react-stately/collections': 3.12.3(react@19.0.0)
'@react-stately/list': 3.12.1(react@19.0.0)
'@react-types/listbox': 3.6.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -10614,7 +10605,7 @@ snapshots:
'@react-stately/tree': 3.8.9(react@19.0.0)
'@react-types/button': 3.13.0(react@19.0.0)
'@react-types/menu': 3.10.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -10688,7 +10679,7 @@ snapshots:
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-stately/radio': 3.10.12(react@19.0.0)
'@react-types/radio': 3.8.8(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -10743,7 +10734,7 @@ snapshots:
dependencies:
'@react-aria/toggle': 3.11.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-stately/toggle': 3.8.3(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@react-types/switch': 3.5.10(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -10776,7 +10767,7 @@ snapshots:
'@react-aria/selection': 3.24.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-stately/tabs': 3.8.1(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@react-types/tabs': 3.3.14(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -10790,7 +10781,7 @@ snapshots:
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-stately/form': 3.1.3(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@react-types/textfield': 3.12.1(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -10844,7 +10835,7 @@ snapshots:
'@react-aria/utils@3.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/ssr': 3.9.8(react@19.0.0)
- '@react-stately/flags': 3.1.0
+ '@react-stately/flags': 3.1.2
'@react-stately/utils': 3.10.8(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
@@ -10852,17 +10843,6 @@ snapshots:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/utils@3.28.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@react-aria/ssr': 3.9.8(react@19.0.0)
- '@react-stately/flags': 3.1.0
- '@react-stately/utils': 3.10.8(react@19.0.0)
- '@react-types/shared': 3.28.0(react@19.0.0)
- '@swc/helpers': 0.5.15
- clsx: 2.1.1
- react: 19.0.0
- react-dom: 19.0.0(react@19.0.0)
-
'@react-aria/utils@3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/ssr': 3.9.8(react@19.0.0)
@@ -10908,7 +10888,7 @@ snapshots:
'@internationalized/date': 3.8.0
'@react-stately/utils': 3.10.8(react@19.0.0)
'@react-types/calendar': 3.7.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -10917,7 +10897,7 @@ snapshots:
'@react-stately/form': 3.1.3(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
'@react-types/checkbox': 3.9.3(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -10954,21 +10934,17 @@ snapshots:
'@react-stately/overlays': 3.6.18(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
'@react-types/datepicker': 3.12.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/flags@3.1.0':
- dependencies:
- '@swc/helpers': 0.5.15
-
'@react-stately/flags@3.1.2':
dependencies:
'@swc/helpers': 0.5.17
'@react-stately/form@3.1.3(react@19.0.0)':
dependencies:
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -10986,7 +10962,7 @@ snapshots:
'@react-stately/collections': 3.12.3(react@19.0.0)
'@react-stately/selection': 3.20.1(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -10994,7 +10970,7 @@ snapshots:
dependencies:
'@react-stately/overlays': 3.6.18(react@19.0.0)
'@react-types/menu': 3.10.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -11026,7 +11002,7 @@ snapshots:
'@react-stately/form': 3.1.3(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
'@react-types/radio': 3.8.8(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -11072,7 +11048,7 @@ snapshots:
'@react-stately/tabs@3.8.1(react@19.0.0)':
dependencies:
'@react-stately/list': 3.12.1(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@react-types/tabs': 3.3.14(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -11103,7 +11079,7 @@ snapshots:
'@react-stately/collections': 3.12.3(react@19.0.0)
'@react-stately/selection': 3.20.1(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -11132,18 +11108,18 @@ snapshots:
'@react-types/accordion@3.0.0-alpha.26(react@19.0.0)':
dependencies:
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
'@react-types/breadcrumbs@3.7.12(react@19.0.0)':
dependencies:
'@react-types/link': 3.6.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
'@react-types/button@3.12.0(react@19.0.0)':
dependencies:
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
'@react-types/button@3.13.0(react@19.0.0)':
@@ -11154,7 +11130,7 @@ snapshots:
'@react-types/calendar@3.7.0(react@19.0.0)':
dependencies:
'@internationalized/date': 3.8.0
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
'@react-types/checkbox@3.9.3(react@19.0.0)':
@@ -11183,7 +11159,7 @@ snapshots:
'@react-types/form@3.7.11(react@19.0.0)':
dependencies:
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
'@react-types/grid@3.3.1(react@19.0.0)':
@@ -11204,7 +11180,7 @@ snapshots:
'@react-types/menu@3.10.0(react@19.0.0)':
dependencies:
'@react-types/overlays': 3.9.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
'@react-types/numberfield@3.8.10(react@19.0.0)':
@@ -11229,7 +11205,7 @@ snapshots:
'@react-types/radio@3.8.8(react@19.0.0)':
dependencies:
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
'@react-types/select@3.9.11(react@19.0.0)':
@@ -11267,12 +11243,12 @@ snapshots:
'@react-types/tabs@3.3.14(react@19.0.0)':
dependencies:
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
'@react-types/textfield@3.12.1(react@19.0.0)':
dependencies:
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
'@react-types/tooltip@3.4.16(react@19.0.0)':
@@ -12070,7 +12046,7 @@ snapshots:
'@vue/compiler-core@3.5.13':
dependencies:
- '@babel/parser': 7.28.0
+ '@babel/parser': 7.28.3
'@vue/shared': 3.5.13
entities: 4.5.0
estree-walker: 2.0.2
@@ -12083,7 +12059,7 @@ snapshots:
'@vue/compiler-sfc@3.5.13':
dependencies:
- '@babel/parser': 7.28.0
+ '@babel/parser': 7.28.3
'@vue/compiler-core': 3.5.13
'@vue/compiler-dom': 3.5.13
'@vue/compiler-ssr': 3.5.13
From b25f1236054116712f62236e6a75e898afc1f996 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Thu, 7 Aug 2025 12:28:15 +0200
Subject: [PATCH 11/45] feat: integrate SWR for data fetching and cache
management across components
- Refactored project and execution modals to use SWR for cache updates instead of router refresh.
- Added `useRefreshCache` hook for centralized cache refresh functions.
- Implemented new client components for login, dashboard, execution, flow, and project pages utilizing SWR hooks.
- Created a global SWR provider to manage configuration and error handling.
- Enhanced loading and error handling UI with skeletons and error cards.
- Updated package dependencies to include SWR.
---
services/frontend/app/auth/login/page.tsx | 11 +-
.../[id]/execution/[executionID]/page.tsx | 62 +----
services/frontend/app/flows/[id]/page.tsx | 84 +-----
services/frontend/app/flows/page.tsx | 77 +-----
services/frontend/app/page.tsx | 59 +----
services/frontend/app/profile/page.tsx | 34 +--
services/frontend/app/projects/[id]/page.tsx | 72 +----
services/frontend/app/projects/page.tsx | 46 +---
services/frontend/app/providers.tsx | 12 +-
services/frontend/app/runners/page.tsx | 44 +--
.../components/auth/login-page-client.tsx | 20 ++
.../components/dashboard/home-page-client.tsx | 73 +++++
.../executions/execution-page-client.tsx | 86 ++++++
.../components/flows/flow/details.tsx | 10 +-
.../components/flows/flow/heading.tsx | 79 +++---
.../components/flows/flow/page-client.tsx | 96 +++++++
.../components/flows/flow/page-skeleton.tsx | 59 +++++
.../frontend/components/flows/page-client.tsx | 90 +++++++
.../components/loading/page-skeleton.tsx | 58 ++++
.../modals/flows/changeMaintenance.tsx | 8 +-
.../components/modals/flows/changeStatus.tsx | 8 +-
.../frontend/components/modals/flows/copy.tsx | 9 +-
.../components/modals/flows/create.tsx | 7 +-
.../components/modals/flows/delete.tsx | 6 +-
.../frontend/components/modals/flows/edit.tsx | 6 +-
.../components/modals/folders/create.tsx | 6 +-
.../components/modals/folders/delete.tsx | 6 +-
.../components/modals/folders/update.tsx | 6 +-
.../modals/projects/changeStatus.tsx | 9 +-
.../components/modals/projects/create.tsx | 6 +-
.../components/modals/projects/delete.tsx | 6 +-
.../components/modals/projects/edit.tsx | 8 +-
.../components/projects/page-client.tsx | 69 +++++
.../projects/project-page-client.tsx | 103 ++++++++
.../components/runners/page-client.tsx | 64 +++++
.../frontend/components/ui/refresh-button.tsx | 75 ++++++
.../components/user/profile-page-client.tsx | 41 +++
services/frontend/lib/swr/api/executions.ts | 25 ++
services/frontend/lib/swr/hooks/flows.ts | 250 ++++++++++++++++++
.../frontend/lib/swr/hooks/useRefreshCache.ts | 80 ++++++
services/frontend/lib/swr/provider.tsx | 29 ++
services/frontend/package.json | 1 +
services/frontend/pnpm-lock.yaml | 14 +
43 files changed, 1363 insertions(+), 551 deletions(-)
create mode 100644 services/frontend/components/auth/login-page-client.tsx
create mode 100644 services/frontend/components/dashboard/home-page-client.tsx
create mode 100644 services/frontend/components/executions/execution-page-client.tsx
create mode 100644 services/frontend/components/flows/flow/page-client.tsx
create mode 100644 services/frontend/components/flows/flow/page-skeleton.tsx
create mode 100644 services/frontend/components/flows/page-client.tsx
create mode 100644 services/frontend/components/loading/page-skeleton.tsx
create mode 100644 services/frontend/components/projects/page-client.tsx
create mode 100644 services/frontend/components/projects/project-page-client.tsx
create mode 100644 services/frontend/components/runners/page-client.tsx
create mode 100644 services/frontend/components/ui/refresh-button.tsx
create mode 100644 services/frontend/components/user/profile-page-client.tsx
create mode 100644 services/frontend/lib/swr/api/executions.ts
create mode 100644 services/frontend/lib/swr/hooks/flows.ts
create mode 100644 services/frontend/lib/swr/hooks/useRefreshCache.ts
create mode 100644 services/frontend/lib/swr/provider.tsx
diff --git a/services/frontend/app/auth/login/page.tsx b/services/frontend/app/auth/login/page.tsx
index e077c1fe..b83c9a92 100644
--- a/services/frontend/app/auth/login/page.tsx
+++ b/services/frontend/app/auth/login/page.tsx
@@ -1,10 +1,5 @@
-import LoginPageComponent from "@/components/auth/loginPage";
-import PageGetSettings from "@/lib/fetch/page/settings";
+import LoginPageClient from "@/components/auth/login-page-client";
-export default async function LoginPage() {
- const settingsData = PageGetSettings();
-
- const [settings] = (await Promise.all([settingsData])) as any;
-
- return ;
+export default function LoginPage() {
+ return ;
}
diff --git a/services/frontend/app/flows/[id]/execution/[executionID]/page.tsx b/services/frontend/app/flows/[id]/execution/[executionID]/page.tsx
index 9c8d6a46..c3612167 100644
--- a/services/frontend/app/flows/[id]/execution/[executionID]/page.tsx
+++ b/services/frontend/app/flows/[id]/execution/[executionID]/page.tsx
@@ -1,10 +1,4 @@
-import { Execution } from "@/components/executions/execution/execution";
-import ErrorCard from "@/components/error/ErrorCard";
-import GetExecution from "@/lib/fetch/executions/execution";
-import GetFlow from "@/lib/fetch/flow/flow";
-import PageGetSettings from "@/lib/fetch/page/settings";
-import GetProjectRunners from "@/lib/fetch/project/runners";
-import GetUserDetails from "@/lib/fetch/user/getDetails";
+import ExecutionPageClient from "@/components/executions/execution-page-client";
export default async function DashboardExecutionPage({
params,
@@ -13,57 +7,5 @@ export default async function DashboardExecutionPage({
}) {
const { id, executionID } = await params;
- const flowData = GetFlow(id);
- const executionData = GetExecution(executionID);
- const settingsData = PageGetSettings();
- const userDetailsData = GetUserDetails();
-
- const [flow, execution, settings, userDetails] = (await Promise.all([
- flowData,
- executionData,
- settingsData,
- userDetailsData,
- ])) as any;
-
- let runnersData;
-
- if (flow.success) {
- runnersData = GetProjectRunners(flow.data.flow.project_id);
- }
- const runners = await runnersData;
-
- return (
- <>
- {execution.success &&
- flow.success &&
- runners.success &&
- settings.success &&
- userDetails.success ? (
-
- ) : (
-
- )}
- >
- );
+ return ;
}
diff --git a/services/frontend/app/flows/[id]/page.tsx b/services/frontend/app/flows/[id]/page.tsx
index 6713a0ec..59d62e53 100644
--- a/services/frontend/app/flows/[id]/page.tsx
+++ b/services/frontend/app/flows/[id]/page.tsx
@@ -1,18 +1,4 @@
-import { Divider, Spacer } from "@heroui/react";
-
-import FlowTabs from "@/components/flows/flow/tabs";
-import GetFlow from "@/lib/fetch/flow/flow";
-import ErrorCard from "@/components/error/ErrorCard";
-import FlowHeading from "@/components/flows/flow/heading";
-import FlowDetails from "@/components/flows/flow/details";
-import GetProjects from "@/lib/fetch/project/all";
-import GetFlowExecutions from "@/lib/fetch/flow/executions";
-import GetUserDetails from "@/lib/fetch/user/getDetails";
-import GetProjectRunners from "@/lib/fetch/project/runners";
-import GetProject from "@/lib/fetch/project/data";
-import GetFolders from "@/lib/fetch/folder/all";
-import PageGetSettings from "@/lib/fetch/page/settings";
-import GetFlows from "@/lib/fetch/flow/all";
+import FlowPageClient from "@/components/flows/flow/page-client";
export default async function FlowPage({
params,
@@ -21,71 +7,5 @@ export default async function FlowPage({
}) {
const { id } = await params;
- const flowsData = GetFlows();
- const flowData = GetFlow(id);
- const projectsData = GetProjects();
- const executionsData = GetFlowExecutions(id);
- const userDetailsData = GetUserDetails();
- const foldersData = GetFolders();
- const settingsData = PageGetSettings();
-
- const [flows, flow, projects, executions, userDetails, folders, settings] =
- (await Promise.all([
- flowsData,
- flowData,
- projectsData,
- executionsData,
- userDetailsData,
- foldersData,
- settingsData,
- ])) as any;
-
- let runnersData;
- let projectdata;
-
- if (flow.success) {
- runnersData = GetProjectRunners(flow.data.flow.project_id);
- projectdata = GetProject(flow.data.flow.project_id);
- }
-
- const [runners, project] = (await Promise.all([
- runnersData,
- projectdata,
- ])) as any;
-
- return (
-
- {flow.success ? (
- <>
-
-
-
-
-
- >
- ) : (
-
- )}
-
- );
+ return ;
}
diff --git a/services/frontend/app/flows/page.tsx b/services/frontend/app/flows/page.tsx
index 7bad1df5..2eac4e22 100644
--- a/services/frontend/app/flows/page.tsx
+++ b/services/frontend/app/flows/page.tsx
@@ -1,76 +1,5 @@
-import { Divider } from "@heroui/react";
+import FlowsPageClient from "@/components/flows/page-client";
-import FlowList from "@/components/flows/list";
-import GetFlows from "@/lib/fetch/flow/all";
-import GetFolders from "@/lib/fetch/folder/all";
-import FlowsHeading from "@/components/flows/heading";
-import GetProjects from "@/lib/fetch/project/all";
-import GetRunningExecutions from "@/lib/fetch/executions/running";
-import GetUserDetails from "@/lib/fetch/user/getDetails";
-import ErrorCard from "@/components/error/ErrorCard";
-import PageGetSettings from "@/lib/fetch/page/settings";
-
-export default async function FlowsPage() {
- const flowsData = GetFlows();
- const foldersData = GetFolders();
- const projectsData = GetProjects();
- const runningExecutionsData = GetRunningExecutions();
- const userDetailsData = GetUserDetails();
- const settingsData = PageGetSettings();
-
- const [flows, folders, projects, runningExecutions, userDetails, settings] =
- (await Promise.all([
- flowsData,
- foldersData,
- projectsData,
- runningExecutionsData,
- userDetailsData,
- settingsData,
- ])) as any;
-
- return (
-
- {projects.success &&
- folders.success &&
- flows.success &&
- userDetails.success &&
- settings.success ? (
- <>
-
-
-
- >
- ) : (
-
- )}
-
- );
+export default function FlowsPage() {
+ return ;
}
diff --git a/services/frontend/app/page.tsx b/services/frontend/app/page.tsx
index dd34617c..16df9d92 100644
--- a/services/frontend/app/page.tsx
+++ b/services/frontend/app/page.tsx
@@ -1,58 +1,5 @@
-import ErrorCard from "@/components/error/ErrorCard";
-import GetFlows from "@/lib/fetch/flow/all";
-import GetRunners from "@/lib/fetch/runner/get";
-import GetUserDetails from "@/lib/fetch/user/getDetails";
-import GetUserStats from "@/lib/fetch/user/stats";
-import DashboardHome from "@/components/dashboard/home";
-import GetExecutionsWithAttention from "@/lib/fetch/executions/attention";
+import DashboardHomePageClient from "@/components/dashboard/home-page-client";
-export default async function DashboardHomePage() {
- const statsData = GetUserStats();
- const flowsData = GetFlows();
- const runnersData = GetRunners();
- const executionsData = GetExecutionsWithAttention();
- const userData = GetUserDetails();
-
- const [stats, flows, runners, executions, user] = (await Promise.all([
- statsData,
- flowsData,
- runnersData,
- executionsData,
- userData,
- ])) as any;
-
- return (
- <>
- {executions.success &&
- flows.success &&
- runners.success &&
- stats.success &&
- user.success ? (
-
- ) : (
-
- )}
- >
- );
+export default function DashboardHomePage() {
+ return ;
}
diff --git a/services/frontend/app/profile/page.tsx b/services/frontend/app/profile/page.tsx
index 304762de..a516e2c1 100644
--- a/services/frontend/app/profile/page.tsx
+++ b/services/frontend/app/profile/page.tsx
@@ -1,36 +1,10 @@
import { cookies } from "next/headers";
-import ErrorCard from "@/components/error/ErrorCard";
-import PageGetSettings from "@/lib/fetch/page/settings";
-import GetUserDetails from "@/lib/fetch/user/getDetails";
-import { UserProfile } from "@/components/user/profile";
+import ProfilePageClient from "@/components/user/profile-page-client";
export default async function ProfilePage() {
- const c = await cookies();
+ const cookieStore = await cookies();
+ const session = cookieStore.get("session")?.value;
- const settingsData = PageGetSettings();
- const userDetailsData = GetUserDetails();
- const session = c.get("session")?.value;
-
- const [settings, userDetails] = (await Promise.all([
- settingsData,
- userDetailsData,
- ])) as any;
-
- return (
- <>
- {settings.success && userDetails.success ? (
-
- ) : (
-
- )}
- >
- );
+ return ;
}
diff --git a/services/frontend/app/projects/[id]/page.tsx b/services/frontend/app/projects/[id]/page.tsx
index f865670f..f4ae22f0 100644
--- a/services/frontend/app/projects/[id]/page.tsx
+++ b/services/frontend/app/projects/[id]/page.tsx
@@ -1,12 +1,4 @@
-import ErrorCard from "@/components/error/ErrorCard";
-import GetFlows from "@/lib/fetch/flow/all";
-import PageGetSettings from "@/lib/fetch/page/settings";
-import GetProjectAuditLogs from "@/lib/fetch/project/audit";
-import GetProject from "@/lib/fetch/project/data";
-import GetProjectRunners from "@/lib/fetch/project/runners";
-import GetProjectApiKeys from "@/lib/fetch/project/tokens";
-import GetUserDetails from "@/lib/fetch/user/getDetails";
-import Project from "@/components/projects/project";
+import ProjectPageClient from "@/components/projects/project-page-client";
export default async function ProjectPage({
params,
@@ -15,65 +7,5 @@ export default async function ProjectPage({
}) {
const { id } = await params;
- const settingsData = PageGetSettings();
- const projectData = GetProject(id);
- const runnersData = GetProjectRunners(id);
- const tokensData = GetProjectApiKeys(id);
- const auditData = GetProjectAuditLogs(id);
- const userDetailsData = GetUserDetails();
- const flowsData = GetFlows();
-
- const [settings, project, runners, tokens, audit, userDetails, flows] =
- (await Promise.all([
- settingsData,
- projectData,
- runnersData,
- tokensData,
- auditData,
- userDetailsData,
- flowsData,
- ])) as any;
-
- return (
- <>
- {audit.success &&
- flows.success &&
- project.success &&
- runners.success &&
- settings.success &&
- tokens.success &&
- userDetails.success ? (
-
- ) : (
-
- )}
- >
- );
+ return ;
}
diff --git a/services/frontend/app/projects/page.tsx b/services/frontend/app/projects/page.tsx
index 4a922362..04d02908 100644
--- a/services/frontend/app/projects/page.tsx
+++ b/services/frontend/app/projects/page.tsx
@@ -1,45 +1,5 @@
-import { Divider } from "@heroui/react";
+import ProjectsPageClient from "@/components/projects/page-client";
-import ErrorCard from "@/components/error/ErrorCard";
-import { ProjectsList } from "@/components/projects/list";
-import PageGetSettings from "@/lib/fetch/page/settings";
-import GetProjects from "@/lib/fetch/project/all";
-import GetUserDetails from "@/lib/fetch/user/getDetails";
-import ProjectsHeading from "@/components/projects/heading";
-
-export default async function ProjectsPage() {
- const projectsData = GetProjects();
- const settingsData = PageGetSettings();
- const userDetailsData = GetUserDetails();
-
- const [projects, settings, userDetails] = (await Promise.all([
- projectsData,
- settingsData,
- userDetailsData,
- ])) as any;
-
- return (
-
- {projects.success && settings.success && userDetails.success ? (
- <>
-
-
-
- >
- ) : (
-
- )}
-
- );
+export default function ProjectsPage() {
+ return ;
}
diff --git a/services/frontend/app/providers.tsx b/services/frontend/app/providers.tsx
index e52d1431..493b1176 100644
--- a/services/frontend/app/providers.tsx
+++ b/services/frontend/app/providers.tsx
@@ -6,6 +6,8 @@ import { useRouter } from "next/navigation";
import * as React from "react";
import { ToastProvider } from "@heroui/react";
+import SWRProvider from "@/lib/swr/provider";
+
type ThemeProviderProps = React.ComponentProps;
export type ProvidersProps = {
@@ -17,9 +19,11 @@ export function Providers({ children, themeProps }: ProvidersProps) {
const router = useRouter();
return (
-
-
- {children}
-
+
+
+
+ {children}
+
+
);
}
diff --git a/services/frontend/app/runners/page.tsx b/services/frontend/app/runners/page.tsx
index c39bfa9d..ff36a552 100644
--- a/services/frontend/app/runners/page.tsx
+++ b/services/frontend/app/runners/page.tsx
@@ -1,43 +1,5 @@
-import { Divider } from "@heroui/react";
+import RunnersPageClient from "@/components/runners/page-client";
-import RunnersList from "@/components/runners/list";
-import GetRunners from "@/lib/fetch/runner/get";
-import GetProjects from "@/lib/fetch/project/all";
-import RunnersHeading from "@/components/runners/heading";
-import GetUserDetails from "@/lib/fetch/user/getDetails";
-import ErrorCard from "@/components/error/ErrorCard";
-
-export default async function RunnersPage() {
- const projectsData = GetProjects();
- const runnersData = GetRunners();
- const userDetailsData = GetUserDetails();
-
- const [projects, runners, userDetails] = (await Promise.all([
- projectsData,
- runnersData,
- userDetailsData,
- ])) as any;
-
- return (
-
- {projects.success && runners.success && userDetails.success ? (
- <>
-
-
-
-
- >
- ) : (
-
- )}
-
- );
+export default function RunnersPage() {
+ return ;
}
diff --git a/services/frontend/components/auth/login-page-client.tsx b/services/frontend/components/auth/login-page-client.tsx
new file mode 100644
index 00000000..33cab8fc
--- /dev/null
+++ b/services/frontend/components/auth/login-page-client.tsx
@@ -0,0 +1,20 @@
+"use client";
+
+import LoginPageComponent from "@/components/auth/loginPage";
+import { PageSkeleton } from "@/components/loading/page-skeleton";
+import { usePageSettings } from "@/lib/swr/hooks/flows";
+
+export default function LoginPageClient() {
+ const { settings, isLoading, isError } = usePageSettings();
+
+ if (isLoading) {
+ return ;
+ }
+
+ if (isError || !settings) {
+ // For login page, we can fall back to some default settings or show a basic login form
+ return ;
+ }
+
+ return ;
+}
diff --git a/services/frontend/components/dashboard/home-page-client.tsx b/services/frontend/components/dashboard/home-page-client.tsx
new file mode 100644
index 00000000..5aceafc0
--- /dev/null
+++ b/services/frontend/components/dashboard/home-page-client.tsx
@@ -0,0 +1,73 @@
+"use client";
+
+import ErrorCard from "@/components/error/ErrorCard";
+import DashboardHome from "@/components/dashboard/home";
+import { PageSkeleton } from "@/components/loading/page-skeleton";
+import {
+ useFlows,
+ useRunners,
+ useUserDetails,
+ useUserStats,
+ useExecutionsWithAttention,
+} from "@/lib/swr/hooks/flows";
+
+export default function DashboardHomePageClient() {
+ const {
+ stats,
+ isLoading: statsLoading,
+ isError: statsError,
+ } = useUserStats();
+ const { flows, isLoading: flowsLoading, isError: flowsError } = useFlows();
+ const {
+ runners,
+ isLoading: runnersLoading,
+ isError: runnersError,
+ } = useRunners();
+ const {
+ executionsWithAttention,
+ isLoading: executionsLoading,
+ isError: executionsError,
+ } = useExecutionsWithAttention();
+ const { user, isLoading: userLoading, isError: userError } = useUserDetails();
+
+ // Check if any essential data is still loading or missing
+ const isLoading =
+ statsLoading ||
+ flowsLoading ||
+ runnersLoading ||
+ executionsLoading ||
+ userLoading ||
+ !stats ||
+ !flows ||
+ !runners ||
+ !executionsWithAttention ||
+ !user;
+
+ // Show loading state if essential data is still loading
+ if (isLoading) {
+ return ;
+ }
+
+ // Show error state
+ const hasError =
+ statsError || flowsError || runnersError || executionsError || userError;
+
+ if (hasError) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+}
diff --git a/services/frontend/components/executions/execution-page-client.tsx b/services/frontend/components/executions/execution-page-client.tsx
new file mode 100644
index 00000000..2bfd5596
--- /dev/null
+++ b/services/frontend/components/executions/execution-page-client.tsx
@@ -0,0 +1,86 @@
+"use client";
+
+import { Execution } from "@/components/executions/execution/execution";
+import ErrorCard from "@/components/error/ErrorCard";
+import { PageSkeleton } from "@/components/loading/page-skeleton";
+import {
+ useFlow,
+ useExecution,
+ usePageSettings,
+ useProjectRunners,
+ useUserDetails,
+} from "@/lib/swr/hooks/flows";
+
+interface ExecutionPageClientProps {
+ flowId: string;
+ executionId: string;
+}
+
+export default function ExecutionPageClient({
+ flowId,
+ executionId,
+}: ExecutionPageClientProps) {
+ const { flow, isLoading: flowLoading, isError: flowError } = useFlow(flowId);
+ const {
+ execution,
+ isLoading: executionLoading,
+ isError: executionError,
+ } = useExecution(executionId);
+ const {
+ settings,
+ isLoading: settingsLoading,
+ isError: settingsError,
+ } = usePageSettings();
+ const { user, isLoading: userLoading, isError: userError } = useUserDetails();
+
+ // Only fetch project runners if we have the flow
+ const projectId = (flow as any)?.project_id;
+ const {
+ runners,
+ isLoading: runnersLoading,
+ isError: runnersError,
+ } = useProjectRunners(projectId || "");
+
+ // Check if any essential data is still loading or missing
+ const isLoading =
+ flowLoading ||
+ executionLoading ||
+ settingsLoading ||
+ userLoading ||
+ !flow ||
+ !execution ||
+ !settings ||
+ !user;
+
+ // Show loading state if essential data is still loading
+ if (isLoading || (projectId && runnersLoading)) {
+ return ;
+ }
+
+ // Show error state
+ const hasError =
+ flowError ||
+ executionError ||
+ settingsError ||
+ userError ||
+ (projectId && runnersError);
+
+ if (hasError) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+}
diff --git a/services/frontend/components/flows/flow/details.tsx b/services/frontend/components/flows/flow/details.tsx
index ad7eaa46..56dba9da 100644
--- a/services/frontend/components/flows/flow/details.tsx
+++ b/services/frontend/components/flows/flow/details.tsx
@@ -5,18 +5,19 @@ import { Icon } from "@iconify/react";
import NumberFlow from "@number-flow/react";
import { useRouter } from "next/navigation";
+import { useFlowExecutions } from "@/lib/swr/hooks/flows";
+
export default function FlowDetails({
flow,
project,
- totalExecutions,
runners,
}: {
flow: any;
project: any;
- totalExecutions: any;
runners: any;
}) {
const router = useRouter();
+ const { total: totalExecutions } = useFlowExecutions(flow.id);
return (
@@ -89,7 +90,10 @@ export default function FlowDetails({
diff --git a/services/frontend/components/flows/flow/heading.tsx b/services/frontend/components/flows/flow/heading.tsx
index 4b76c847..6ef41c97 100644
--- a/services/frontend/components/flows/flow/heading.tsx
+++ b/services/frontend/components/flows/flow/heading.tsx
@@ -3,11 +3,12 @@
import { addToast, Button, Divider, useDisclosure } from "@heroui/react";
import { Icon } from "@iconify/react";
-import APIStartExecution from "@/lib/fetch/executions/start";
-import Reloader from "@/components/reloader/Reloader";
import ScheduleExecutionModal from "@/components/modals/executions/schedule";
import EditFlowModal from "@/components/modals/flows/edit";
import canEditProject from "@/lib/functions/canEditProject";
+import RefreshButton from "@/components/ui/refresh-button";
+import { startExecution } from "@/lib/swr/api/executions";
+import { useFlowExecutions } from "@/lib/swr/hooks/flows";
export default function FlowHeading({
flow,
@@ -27,6 +28,33 @@ export default function FlowHeading({
const editFlowModal = useDisclosure();
const scheduleExecutionModal = useDisclosure();
+ // Use SWR for auto-refreshing flow executions data
+ const { refresh: refreshExecutions, isLoading: executionsLoading } =
+ useFlowExecutions(flow.id);
+
+ const handleExecuteFlow = async () => {
+ const result = await startExecution(flow.id);
+
+ if (result.success) {
+ addToast({
+ title: "Execution Started",
+ color: "success",
+ });
+ // Immediately refresh executions data
+ refreshExecutions();
+ } else {
+ addToast({
+ title: "Execution start failed",
+ description: result.error,
+ color: "danger",
+ });
+ }
+ };
+
+ const handleRefresh = async () => {
+ await refreshExecutions();
+ };
+
return (
@@ -58,22 +86,7 @@ export default function FlowHeading({
}
startContent={
}
variant="solid"
- onPress={() => {
- APIStartExecution(flow.id)
- .then(() => {
- addToast({
- title: "Execution Started",
- color: "success",
- });
- })
- .catch((err) => {
- addToast({
- title: "Execution start failed",
- description: err.message,
- color: "danger",
- });
- });
- }}
+ onPress={handleExecuteFlow}
>
Execute
@@ -93,7 +106,11 @@ export default function FlowHeading({
Edit
-
+
{/* Mobile */}
@@ -112,25 +129,15 @@ export default function FlowHeading({
color="primary"
startContent={ }
variant="solid"
- onPress={() => {
- APIStartExecution(flow.id)
- .then(() => {
- addToast({
- title: "Execution Started",
- color: "success",
- });
- })
- .catch((err) => {
- addToast({
- title: "Execution start failed",
- description: err.message,
- color: "danger",
- });
- });
- }}
+ onPress={handleExecuteFlow}
/>
-
+
;
+ }
+
+ // Show error state
+ if (flowError || !flow) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+ );
+}
diff --git a/services/frontend/components/flows/flow/page-skeleton.tsx b/services/frontend/components/flows/flow/page-skeleton.tsx
new file mode 100644
index 00000000..6793d531
--- /dev/null
+++ b/services/frontend/components/flows/flow/page-skeleton.tsx
@@ -0,0 +1,59 @@
+"use client";
+
+import { Card, CardBody, Skeleton } from "@heroui/react";
+
+export default function FlowPageSkeleton() {
+ return (
+
+ {/* Header skeleton */}
+
+
+ {/* Divider */}
+
+
+ {/* Details cards skeleton */}
+
+ {Array.from({ length: 4 }).map((_, i) => (
+
+
+
+
+
+ ))}
+
+
+ {/* Tabs skeleton */}
+
+
+ {Array.from({ length: 4 }).map((_, i) => (
+
+ ))}
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/services/frontend/components/flows/page-client.tsx b/services/frontend/components/flows/page-client.tsx
new file mode 100644
index 00000000..6c14d71a
--- /dev/null
+++ b/services/frontend/components/flows/page-client.tsx
@@ -0,0 +1,90 @@
+"use client";
+
+import { Divider } from "@heroui/react";
+
+import FlowList from "@/components/flows/list";
+import FlowsHeading from "@/components/flows/heading";
+import ErrorCard from "@/components/error/ErrorCard";
+import { PageSkeleton } from "@/components/loading/page-skeleton";
+import {
+ useFlows,
+ useFolders,
+ useProjects,
+ useRunningExecutions,
+ useUserDetails,
+ usePageSettings,
+} from "@/lib/swr/hooks/flows";
+
+export default function FlowsPageClient() {
+ const { flows, isLoading: flowsLoading, isError: flowsError } = useFlows();
+ const {
+ folders,
+ isLoading: foldersLoading,
+ isError: foldersError,
+ } = useFolders();
+ const {
+ projects,
+ isLoading: projectsLoading,
+ isError: projectsError,
+ } = useProjects();
+ const { runningExecutions, isLoading: runningExecutionsLoading } =
+ useRunningExecutions();
+ const { user, isLoading: userLoading, isError: userError } = useUserDetails();
+ const {
+ settings,
+ isLoading: settingsLoading,
+ isError: settingsError,
+ } = usePageSettings();
+
+ // Check if any essential data is still loading or missing
+ const isLoading =
+ flowsLoading ||
+ foldersLoading ||
+ projectsLoading ||
+ userLoading ||
+ settingsLoading ||
+ !flows ||
+ !folders ||
+ !projects ||
+ !user ||
+ !settings;
+
+ // Show loading state if essential data is still loading
+ if (isLoading || runningExecutionsLoading) {
+ return ;
+ }
+
+ // Show error state
+ const hasError =
+ flowsError || foldersError || projectsError || userError || settingsError;
+
+ if (hasError) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+ );
+}
diff --git a/services/frontend/components/loading/page-skeleton.tsx b/services/frontend/components/loading/page-skeleton.tsx
new file mode 100644
index 00000000..f86bae7f
--- /dev/null
+++ b/services/frontend/components/loading/page-skeleton.tsx
@@ -0,0 +1,58 @@
+import { Card, CardBody, Skeleton, Spacer } from "@heroui/react";
+
+export function PageSkeleton() {
+ return (
+
+ {/* Heading skeleton */}
+
+
+
+
+ {/* Divider skeleton */}
+
+
+
+
+
+
+ {/* Content skeleton */}
+
+ {Array.from({ length: 6 }).map((_, i) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/services/frontend/components/modals/flows/changeMaintenance.tsx b/services/frontend/components/modals/flows/changeMaintenance.tsx
index 9b64d75a..1fb443dd 100644
--- a/services/frontend/components/modals/flows/changeMaintenance.tsx
+++ b/services/frontend/components/modals/flows/changeMaintenance.tsx
@@ -11,11 +11,11 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import ChangeFlowMaintenance from "@/lib/fetch/flow/PUT/ChangeFlowMaintenance";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function ChangeFlowMaintenanceModal({
disclosure,
@@ -26,7 +26,7 @@ export default function ChangeFlowMaintenanceModal({
flow: any;
maintenance: any;
}) {
- const router = useRouter();
+ const { refreshFlowData } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
@@ -59,7 +59,7 @@ export default function ChangeFlowMaintenanceModal({
setErrorText("");
setErrorMessage("");
onOpenChange();
- router.refresh();
+ refreshFlowData(); // Refresh SWR cache instead of router
addToast({
title: "Flow",
description: "Flow maintenance updated successfully",
@@ -70,7 +70,7 @@ export default function ChangeFlowMaintenanceModal({
setError(true);
setErrorText(res.error);
setErrorMessage(res.message);
- router.refresh();
+ refreshFlowData(); // Refresh SWR cache instead of router
addToast({
title: "Flow",
description: "Failed to update flow maintenance",
diff --git a/services/frontend/components/modals/flows/changeStatus.tsx b/services/frontend/components/modals/flows/changeStatus.tsx
index cff17766..b37fc976 100644
--- a/services/frontend/components/modals/flows/changeStatus.tsx
+++ b/services/frontend/components/modals/flows/changeStatus.tsx
@@ -11,11 +11,11 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import ChangeFlowStatus from "@/lib/fetch/admin/PUT/ChangeFlowStatus";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function ChangeFlowStatusModal({
disclosure,
@@ -26,7 +26,7 @@ export default function ChangeFlowStatusModal({
flow: any;
status: any;
}) {
- const router = useRouter();
+ const { refreshFlowData } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
@@ -59,7 +59,7 @@ export default function ChangeFlowStatusModal({
setErrorMessage("");
setErrorText("");
onOpenChange();
- router.refresh();
+ refreshFlowData(); // Refresh SWR cache instead of router
addToast({
title: "Flow",
description: "Flow status updated successfully",
@@ -70,7 +70,7 @@ export default function ChangeFlowStatusModal({
setError(true);
setErrorText(res.error);
setErrorMessage(res.message);
- router.refresh();
+ refreshFlowData(); // Refresh SWR cache instead of router
addToast({
title: "Flow",
description: "Failed to update flow status",
diff --git a/services/frontend/components/modals/flows/copy.tsx b/services/frontend/components/modals/flows/copy.tsx
index fc303134..17251d5a 100644
--- a/services/frontend/components/modals/flows/copy.tsx
+++ b/services/frontend/components/modals/flows/copy.tsx
@@ -15,13 +15,13 @@ import {
SelectItem,
Switch,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";
import { Icon } from "@iconify/react";
import GetProjectRunners from "@/lib/fetch/project/runners";
import ErrorCard from "@/components/error/ErrorCard";
import CopyFlow from "@/lib/fetch/flow/POST/CopyFlow";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
import RowSteps from "../../steps/row-steps";
@@ -36,7 +36,8 @@ export default function CopyFlowModal({
projects: any;
disclosure: UseDisclosureReturn;
}) {
- const router = useRouter();
+ const { refreshFlowData, refreshFolders, refreshProjects } =
+ useRefreshCache();
// create modal
const { isOpen, onOpenChange } = disclosure;
@@ -120,7 +121,9 @@ export default function CopyFlowModal({
}
if (response.success) {
- router.refresh();
+ refreshFlowData(); // Refresh SWR cache instead of router
+ refreshProjects(); // Refresh SWR cache instead of router
+ refreshFolders();
onOpenChange();
setName("");
setDescription("");
diff --git a/services/frontend/components/modals/flows/create.tsx b/services/frontend/components/modals/flows/create.tsx
index aeb6dc24..f0c9a467 100644
--- a/services/frontend/components/modals/flows/create.tsx
+++ b/services/frontend/components/modals/flows/create.tsx
@@ -15,13 +15,14 @@ import {
SelectItem,
Switch,
} from "@heroui/react";
-import { useRouter, useSearchParams } from "next/navigation";
+import { useSearchParams } from "next/navigation";
import React, { useEffect, useState } from "react";
import { Icon } from "@iconify/react";
import GetProjectRunners from "@/lib/fetch/project/runners";
import CreateFlow from "@/lib/fetch/flow/POST/CreateFlow";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
import RowSteps from "../../steps/row-steps";
@@ -34,7 +35,7 @@ export default function CreateFlowModal({
projects: any;
disclosure: UseDisclosureReturn;
}) {
- const router = useRouter();
+ const { refreshFlowData } = useRefreshCache();
// create modal
const { isOpen, onOpenChange } = disclosure;
@@ -115,7 +116,7 @@ export default function CreateFlowModal({
}
if (response.success) {
- router.refresh();
+ refreshFlowData(); // Refresh SWR cache (for new flows, no specific ID needed)
onOpenChange();
setName("");
setDescription("");
diff --git a/services/frontend/components/modals/flows/delete.tsx b/services/frontend/components/modals/flows/delete.tsx
index 2c3e36a1..7d2248fd 100644
--- a/services/frontend/components/modals/flows/delete.tsx
+++ b/services/frontend/components/modals/flows/delete.tsx
@@ -12,12 +12,12 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import { Icon } from "@iconify/react";
import ErrorCard from "@/components/error/ErrorCard";
import DeleteFlow from "@/lib/fetch/flow/DELETE/DeleteFlow";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function DeleteFlowModal({
disclosure,
@@ -26,8 +26,8 @@ export default function DeleteFlowModal({
disclosure: UseDisclosureReturn;
flow: any;
}) {
- const router = useRouter();
const { isOpen, onOpenChange } = disclosure;
+ const { refreshFlowData } = useRefreshCache();
const [isLoading, setIsLoading] = React.useState(false);
const [error, setError] = React.useState(false);
@@ -54,7 +54,7 @@ export default function DeleteFlowModal({
}
if (res.success) {
- router.refresh();
+ refreshFlowData(); // Refresh SWR cache instead of router
onOpenChange();
setIsLoading(false);
setError(false);
diff --git a/services/frontend/components/modals/flows/edit.tsx b/services/frontend/components/modals/flows/edit.tsx
index d7727e4a..a5f516b7 100644
--- a/services/frontend/components/modals/flows/edit.tsx
+++ b/services/frontend/components/modals/flows/edit.tsx
@@ -17,13 +17,13 @@ import {
SelectItem,
Switch,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useEffect } from "react";
import { Icon } from "@iconify/react";
import GetProjectRunners from "@/lib/fetch/project/runners";
import UpdateFlow from "@/lib/fetch/flow/PUT/UpdateFlow";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function EditFlowModal({
targetFlow,
@@ -36,7 +36,7 @@ export default function EditFlowModal({
folders: any;
disclosure: UseDisclosureReturn;
}) {
- const router = useRouter();
+ const { refreshFlowData } = useRefreshCache();
// create modal
const { isOpen, onOpenChange, onClose } = disclosure;
@@ -120,7 +120,7 @@ export default function EditFlowModal({
}
if (response.success) {
- router.refresh();
+ refreshFlowData(targetFlow.id); // Refresh SWR cache with specific flow ID
onOpenChange();
setIsLoading(false);
addToast({
diff --git a/services/frontend/components/modals/folders/create.tsx b/services/frontend/components/modals/folders/create.tsx
index 6132fb7d..8f8e68d8 100644
--- a/services/frontend/components/modals/folders/create.tsx
+++ b/services/frontend/components/modals/folders/create.tsx
@@ -14,12 +14,12 @@ import {
Select,
SelectItem,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useState } from "react";
import { Icon } from "@iconify/react";
import ErrorCard from "@/components/error/ErrorCard";
import CreateFolder from "@/lib/fetch/folder/POST/create";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function CreateFolderModal({
disclosure,
@@ -30,8 +30,8 @@ export default function CreateFolderModal({
projects: any;
folders: any;
}) {
- const router = useRouter();
const { isOpen, onOpenChange } = disclosure;
+ const { refreshFolders } = useRefreshCache();
const [errors] = useState({});
const [apiError, setApiError] = useState(false);
@@ -75,7 +75,7 @@ export default function CreateFolderModal({
setApiErrorText("");
setApiErrorMessage("");
- router.refresh();
+ refreshFolders(); // Refresh SWR cache instead of router
addToast({
title: "Folder",
description: "Folder created successfully",
diff --git a/services/frontend/components/modals/folders/delete.tsx b/services/frontend/components/modals/folders/delete.tsx
index 39e20f4b..e9ddf8db 100644
--- a/services/frontend/components/modals/folders/delete.tsx
+++ b/services/frontend/components/modals/folders/delete.tsx
@@ -12,12 +12,12 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import { Icon } from "@iconify/react";
import ErrorCard from "@/components/error/ErrorCard";
import DeleteFolder from "@/lib/fetch/folder/delete";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function DeleteFolderModal({
disclosure,
@@ -26,8 +26,8 @@ export default function DeleteFolderModal({
disclosure: UseDisclosureReturn;
folder: any;
}) {
- const router = useRouter();
const { isOpen, onOpenChange } = disclosure;
+ const { refreshFolders } = useRefreshCache();
const [isLoading, setIsLoading] = React.useState(false);
const [error, setError] = React.useState(false);
@@ -54,7 +54,7 @@ export default function DeleteFolderModal({
}
if (res.success) {
- router.refresh();
+ refreshFolders(); // Refresh SWR cache instead of router
onOpenChange();
setIsLoading(false);
setError(false);
diff --git a/services/frontend/components/modals/folders/update.tsx b/services/frontend/components/modals/folders/update.tsx
index f3375359..ae46ce64 100644
--- a/services/frontend/components/modals/folders/update.tsx
+++ b/services/frontend/components/modals/folders/update.tsx
@@ -14,12 +14,12 @@ import {
Select,
SelectItem,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useState } from "react";
import { Icon } from "@iconify/react";
import ErrorCard from "@/components/error/ErrorCard";
import UpdateFolder from "@/lib/fetch/folder/update";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function UpdateFolderModal({
disclosure,
@@ -32,8 +32,8 @@ export default function UpdateFolderModal({
folders: any;
folder: any;
}) {
- const router = useRouter();
const { isOpen, onOpenChange } = disclosure;
+ const { refreshFolder } = useRefreshCache();
const [errors] = useState({});
const [apiError, setApiError] = useState(false);
@@ -78,7 +78,7 @@ export default function UpdateFolderModal({
setApiErrorText("");
setApiErrorMessage("");
- router.refresh();
+ refreshFolder(folder.id); // Refresh SWR cache with specific folder ID
addToast({
title: "Folder",
description: "Folder updated successfully",
diff --git a/services/frontend/components/modals/projects/changeStatus.tsx b/services/frontend/components/modals/projects/changeStatus.tsx
index 559336b7..c38e709e 100644
--- a/services/frontend/components/modals/projects/changeStatus.tsx
+++ b/services/frontend/components/modals/projects/changeStatus.tsx
@@ -11,11 +11,11 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import ChangeProjectStatus from "@/lib/fetch/admin/PUT/ChangeProjectStatus";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function ChangeProjectStatusModal({
disclosure,
@@ -26,9 +26,8 @@ export default function ChangeProjectStatusModal({
project: any;
status: any;
}) {
- const router = useRouter();
-
const { isOpen, onOpenChange } = disclosure;
+ const { refreshProjects } = useRefreshCache();
const [disableReason, setDisableReason] = React.useState("");
const [isLoading, setLoading] = React.useState(false);
@@ -66,7 +65,7 @@ export default function ChangeProjectStatusModal({
setErrorText("");
setErrorMessage("");
onOpenChange();
- router.refresh();
+ refreshProjects(); // Refresh SWR cache instead of router
addToast({
title: "Project",
description: "Project status updated successfully",
@@ -78,7 +77,7 @@ export default function ChangeProjectStatusModal({
setError(true);
setErrorText(res.error);
setErrorMessage(res.message);
- router.refresh();
+ refreshProjects(); // Refresh SWR cache instead of router
addToast({
title: "Project",
description: "Failed to update project status",
diff --git a/services/frontend/components/modals/projects/create.tsx b/services/frontend/components/modals/projects/create.tsx
index 5279e1cd..3b24a20e 100644
--- a/services/frontend/components/modals/projects/create.tsx
+++ b/services/frontend/components/modals/projects/create.tsx
@@ -16,12 +16,12 @@ import {
Select,
SelectItem,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useEffect } from "react";
import { ColorPicker, useColor } from "react-color-palette";
import CreateProject from "@/lib/fetch/project/POST/CreateProject";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
import "react-color-palette/css";
export default function CreateProjectModal({
@@ -29,9 +29,9 @@ export default function CreateProjectModal({
}: {
disclosure: UseDisclosureReturn;
}) {
- const router = useRouter();
const { isOpen, onOpenChange } = disclosure;
const [icons, setIcons] = React.useState([]);
+ const { refreshProjects } = useRefreshCache();
const [color, setColor] = useColor("#5213d7");
@@ -82,7 +82,7 @@ export default function CreateProjectModal({
}
if (res.success) {
- router.refresh();
+ refreshProjects(); // Refresh SWR cache instead of router
onOpenChange();
setApiError(false);
setApiErrorText("");
diff --git a/services/frontend/components/modals/projects/delete.tsx b/services/frontend/components/modals/projects/delete.tsx
index 3df5a22b..dbda9261 100644
--- a/services/frontend/components/modals/projects/delete.tsx
+++ b/services/frontend/components/modals/projects/delete.tsx
@@ -12,12 +12,12 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import { Icon } from "@iconify/react";
import DeleteProject from "@/lib/fetch/project/DELETE/DeleteProject";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function DeleteProjectModal({
disclosure,
@@ -26,8 +26,8 @@ export default function DeleteProjectModal({
disclosure: UseDisclosureReturn;
project: any;
}) {
- const router = useRouter();
const { isOpen, onOpenChange } = disclosure;
+ const { refreshProjects } = useRefreshCache();
const [isLoading, setIsLoading] = React.useState(false);
const [error, setError] = React.useState(false);
@@ -54,7 +54,7 @@ export default function DeleteProjectModal({
}
if (res.success) {
- router.refresh();
+ refreshProjects(); // Refresh SWR cache instead of router
onOpenChange();
setIsLoading(false);
setError(false);
diff --git a/services/frontend/components/modals/projects/edit.tsx b/services/frontend/components/modals/projects/edit.tsx
index f38b34fb..bb854577 100644
--- a/services/frontend/components/modals/projects/edit.tsx
+++ b/services/frontend/components/modals/projects/edit.tsx
@@ -16,7 +16,6 @@ import {
Select,
SelectItem,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useEffect } from "react";
import { ColorPicker, useColor } from "react-color-palette";
import tinycolor from "tinycolor2";
@@ -24,6 +23,7 @@ import tinycolor from "tinycolor2";
import UpdateProject from "@/lib/fetch/project/PUT/UpdateProject";
import ErrorCard from "@/components/error/ErrorCard";
import "react-color-palette/css";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function EditProjectModal({
disclosure,
@@ -32,10 +32,10 @@ export default function EditProjectModal({
disclosure: UseDisclosureReturn;
project: any;
}) {
- const router = useRouter();
const { isOpen, onOpenChange } = disclosure;
- const [icons, setIcons] = React.useState([]);
+ const { refreshProject } = useRefreshCache();
+ const [icons, setIcons] = React.useState([]);
const [color, setColor] = useColor("");
const [errors] = React.useState({});
@@ -97,7 +97,7 @@ export default function EditProjectModal({
}
if (res.success) {
- router.refresh();
+ refreshProject(project.id); // Refresh SWR cache instead of router
onOpenChange();
setApiError(false);
setApiErrorText("");
diff --git a/services/frontend/components/projects/page-client.tsx b/services/frontend/components/projects/page-client.tsx
new file mode 100644
index 00000000..c023e21a
--- /dev/null
+++ b/services/frontend/components/projects/page-client.tsx
@@ -0,0 +1,69 @@
+"use client";
+
+import { Divider } from "@heroui/react";
+
+import ErrorCard from "@/components/error/ErrorCard";
+import { ProjectsList } from "@/components/projects/list";
+import ProjectsHeading from "@/components/projects/heading";
+import { PageSkeleton } from "@/components/loading/page-skeleton";
+import {
+ useProjects,
+ usePageSettings,
+ useUserDetails,
+} from "@/lib/swr/hooks/flows";
+
+export default function ProjectsPageClient() {
+ const {
+ projects,
+ pendingProjects,
+ isLoading: projectsLoading,
+ isError: projectsError,
+ } = useProjects();
+ const {
+ settings,
+ isLoading: settingsLoading,
+ isError: settingsError,
+ } = usePageSettings();
+ const { user, isLoading: userLoading, isError: userError } = useUserDetails();
+
+ // Check if any essential data is still loading or missing
+ const isLoading =
+ projectsLoading ||
+ settingsLoading ||
+ userLoading ||
+ !projects ||
+ !settings ||
+ !user;
+
+ // Show loading state if essential data is still loading
+ if (isLoading) {
+ return ;
+ }
+
+ // Show error state
+ const hasError = projectsError || settingsError || userError;
+
+ if (hasError) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+ );
+}
diff --git a/services/frontend/components/projects/project-page-client.tsx b/services/frontend/components/projects/project-page-client.tsx
new file mode 100644
index 00000000..dfa94442
--- /dev/null
+++ b/services/frontend/components/projects/project-page-client.tsx
@@ -0,0 +1,103 @@
+"use client";
+
+import ErrorCard from "@/components/error/ErrorCard";
+import Project from "@/components/projects/project";
+import { PageSkeleton } from "@/components/loading/page-skeleton";
+import {
+ useFlows,
+ usePageSettings,
+ useProject,
+ useProjectRunners,
+ useProjectApiKeys,
+ useProjectAuditLogs,
+ useUserDetails,
+} from "@/lib/swr/hooks/flows";
+
+interface ProjectPageClientProps {
+ projectId: string;
+}
+
+export default function ProjectPageClient({
+ projectId,
+}: ProjectPageClientProps) {
+ const {
+ settings,
+ isLoading: settingsLoading,
+ isError: settingsError,
+ } = usePageSettings();
+ const {
+ project,
+ isLoading: projectLoading,
+ isError: projectError,
+ } = useProject(projectId);
+ const {
+ runners,
+ isLoading: runnersLoading,
+ isError: runnersError,
+ } = useProjectRunners(projectId);
+ const {
+ tokens,
+ isLoading: tokensLoading,
+ isError: tokensError,
+ } = useProjectApiKeys(projectId);
+ const {
+ audit,
+ isLoading: auditLoading,
+ isError: auditError,
+ } = useProjectAuditLogs(projectId);
+ const { user, isLoading: userLoading, isError: userError } = useUserDetails();
+ const { flows, isLoading: flowsLoading, isError: flowsError } = useFlows();
+
+ // Check if any essential data is still loading or missing
+ const isLoading =
+ settingsLoading ||
+ projectLoading ||
+ runnersLoading ||
+ tokensLoading ||
+ auditLoading ||
+ userLoading ||
+ flowsLoading ||
+ !settings ||
+ !project ||
+ !runners ||
+ !tokens ||
+ !audit ||
+ !user ||
+ !flows;
+
+ // Show loading state if essential data is still loading
+ if (isLoading) {
+ return ;
+ }
+
+ // Show error state
+ const hasError =
+ settingsError ||
+ projectError ||
+ runnersError ||
+ tokensError ||
+ auditError ||
+ userError ||
+ flowsError;
+
+ if (hasError) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+}
diff --git a/services/frontend/components/runners/page-client.tsx b/services/frontend/components/runners/page-client.tsx
new file mode 100644
index 00000000..8230c849
--- /dev/null
+++ b/services/frontend/components/runners/page-client.tsx
@@ -0,0 +1,64 @@
+"use client";
+
+import { Divider } from "@heroui/react";
+
+import RunnersList from "@/components/runners/list";
+import RunnersHeading from "@/components/runners/heading";
+import ErrorCard from "@/components/error/ErrorCard";
+import { PageSkeleton } from "@/components/loading/page-skeleton";
+import { useRunners, useProjects, useUserDetails } from "@/lib/swr/hooks/flows";
+
+export default function RunnersPageClient() {
+ const {
+ runners,
+ isLoading: runnersLoading,
+ isError: runnersError,
+ } = useRunners();
+ const {
+ projects,
+ isLoading: projectsLoading,
+ isError: projectsError,
+ } = useProjects();
+ const { user, isLoading: userLoading, isError: userError } = useUserDetails();
+
+ // Check if any essential data is still loading or missing
+ const isLoading =
+ runnersLoading ||
+ projectsLoading ||
+ userLoading ||
+ !runners ||
+ !projects ||
+ !user;
+
+ // Show loading state if essential data is still loading
+ if (isLoading) {
+ return ;
+ }
+
+ // Show error state
+ const hasError = runnersError || projectsError || userError;
+
+ if (hasError) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+ );
+}
diff --git a/services/frontend/components/ui/refresh-button.tsx b/services/frontend/components/ui/refresh-button.tsx
new file mode 100644
index 00000000..d0b16b31
--- /dev/null
+++ b/services/frontend/components/ui/refresh-button.tsx
@@ -0,0 +1,75 @@
+"use client";
+
+import { Button } from "@heroui/react";
+import { Icon } from "@iconify/react";
+import { ReactNode, useState } from "react";
+
+interface RefreshButtonProps {
+ onRefresh: () => Promise | void;
+ isLoading?: boolean;
+ variant?:
+ | "solid"
+ | "bordered"
+ | "light"
+ | "flat"
+ | "faded"
+ | "shadow"
+ | "ghost";
+ color?:
+ | "default"
+ | "primary"
+ | "secondary"
+ | "success"
+ | "warning"
+ | "danger";
+ size?: "sm" | "md" | "lg";
+ isIconOnly?: boolean;
+ children?: ReactNode;
+}
+
+export default function RefreshButton({
+ onRefresh,
+ isLoading: externalLoading,
+ variant = "flat",
+ color = "default",
+ size = "md",
+ isIconOnly = false,
+ children,
+}: RefreshButtonProps) {
+ const [internalLoading, setInternalLoading] = useState(false);
+
+ const isLoading = externalLoading || internalLoading;
+
+ const handleRefresh = async () => {
+ if (isLoading) return;
+
+ setInternalLoading(true);
+ try {
+ await onRefresh();
+ } finally {
+ setInternalLoading(false);
+ }
+ };
+
+ return (
+
+ ) : undefined
+ }
+ variant={variant}
+ onPress={handleRefresh}
+ >
+ {isIconOnly
+ ? !isLoading && (
+
+ )
+ : children || "Refresh"}
+
+ );
+}
diff --git a/services/frontend/components/user/profile-page-client.tsx b/services/frontend/components/user/profile-page-client.tsx
new file mode 100644
index 00000000..ffcf8e86
--- /dev/null
+++ b/services/frontend/components/user/profile-page-client.tsx
@@ -0,0 +1,41 @@
+"use client";
+
+import ErrorCard from "@/components/error/ErrorCard";
+import { UserProfile } from "@/components/user/profile";
+import { PageSkeleton } from "@/components/loading/page-skeleton";
+import { usePageSettings, useUserDetails } from "@/lib/swr/hooks/flows";
+
+interface ProfilePageClientProps {
+ session?: string;
+}
+
+export default function ProfilePageClient({ session }: ProfilePageClientProps) {
+ const {
+ settings,
+ isLoading: settingsLoading,
+ isError: settingsError,
+ } = usePageSettings();
+ const { user, isLoading: userLoading, isError: userError } = useUserDetails();
+
+ // Check if any essential data is still loading or missing
+ const isLoading = settingsLoading || userLoading || !settings || !user;
+
+ // Show loading state if essential data is still loading
+ if (isLoading) {
+ return ;
+ }
+
+ // Show error state
+ const hasError = settingsError || userError;
+
+ if (hasError) {
+ return (
+
+ );
+ }
+
+ return ;
+}
diff --git a/services/frontend/lib/swr/api/executions.ts b/services/frontend/lib/swr/api/executions.ts
new file mode 100644
index 00000000..a459e392
--- /dev/null
+++ b/services/frontend/lib/swr/api/executions.ts
@@ -0,0 +1,25 @@
+import APIStartExecution from "@/lib/fetch/executions/start";
+
+// Client-side API helpers for mutations
+export async function startExecution(
+ flowId: string,
+): Promise<{ success: boolean; error?: string }> {
+ try {
+ const result = await APIStartExecution(flowId);
+
+ if (result.success) {
+ return { success: true };
+ } else {
+ return {
+ success: false,
+ error:
+ "message" in result ? result.message : "Failed to start execution",
+ };
+ }
+ } catch (error) {
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "Unknown error occurred",
+ };
+ }
+}
diff --git a/services/frontend/lib/swr/hooks/flows.ts b/services/frontend/lib/swr/hooks/flows.ts
new file mode 100644
index 00000000..48456a23
--- /dev/null
+++ b/services/frontend/lib/swr/hooks/flows.ts
@@ -0,0 +1,250 @@
+import useSWR from "swr";
+
+import { GetFlow } from "@/lib/fetch/flow/flow";
+import { GetFlowExecutions } from "@/lib/fetch/flow/executions";
+import GetFlows from "@/lib/fetch/flow/all";
+import GetProjects from "@/lib/fetch/project/all";
+import GetUserDetails from "@/lib/fetch/user/getDetails";
+import GetFolders from "@/lib/fetch/folder/all";
+import PageGetSettings from "@/lib/fetch/page/settings";
+import GetProjectRunners from "@/lib/fetch/project/runners";
+import GetProject from "@/lib/fetch/project/data";
+import GetRunners from "@/lib/fetch/runner/get";
+import GetRunningExecutions from "@/lib/fetch/executions/running";
+import GetUserStats from "@/lib/fetch/user/stats";
+import GetExecutionsWithAttention from "@/lib/fetch/executions/attention";
+import GetProjectAuditLogs from "@/lib/fetch/project/audit";
+import GetProjectApiKeys from "@/lib/fetch/project/tokens";
+import GetExecution from "@/lib/fetch/executions/execution";
+
+// Hook for fetching a single flow
+export function useFlow(flowId: string) {
+ const { data, error, mutate, isLoading } = useSWR(
+ flowId ? `flow-${flowId}` : null,
+ () => GetFlow(flowId),
+ );
+
+ return {
+ flow: data?.success ? data.data.flow : null,
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching flow executions
+export function useFlowExecutions(flowId: string) {
+ const { data, error, mutate, isLoading } = useSWR(
+ flowId ? `flow-executions-${flowId}` : null,
+ () => GetFlowExecutions(flowId, 50, 0),
+ );
+
+ return {
+ executions: data?.success ? data.data.executions : [],
+ total: data?.success ? data.data.total : 0,
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching all flows
+export function useFlows() {
+ const { data, error, mutate, isLoading } = useSWR("flows", () => GetFlows());
+
+ return {
+ flows: data?.success ? data.data.flows : [],
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching all projects
+export function useProjects() {
+ const { data, error, mutate, isLoading } = useSWR("projects", () =>
+ GetProjects(),
+ );
+
+ return {
+ projects: data?.success ? data.data.projects : [],
+ pendingProjects: data?.success ? data.data.pending_projects : [],
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching user details
+export function useUserDetails() {
+ const { data, error, mutate, isLoading } = useSWR("user-details", () =>
+ GetUserDetails(),
+ );
+
+ return {
+ user: data?.success ? data.data.user : null,
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching folders
+export function useFolders() {
+ const { data, error, mutate, isLoading } = useSWR("folders", () =>
+ GetFolders(),
+ );
+
+ return {
+ folders: data?.success ? data.data.folders : [],
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching page settings
+export function usePageSettings() {
+ const { data, error, mutate, isLoading } = useSWR("page-settings", () =>
+ PageGetSettings(),
+ );
+
+ return {
+ settings: data?.success ? data.data.settings : {},
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching project runners
+export function useProjectRunners(projectId: string) {
+ const { data, error, mutate, isLoading } = useSWR(
+ projectId ? `project-runners-${projectId}` : null,
+ () => GetProjectRunners(projectId),
+ );
+
+ return {
+ runners: data?.success ? data.data.runners : [],
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching a single project
+export function useProject(projectId: string) {
+ const { data, error, mutate, isLoading } = useSWR(
+ projectId ? `project-${projectId}` : null,
+ () => GetProject(projectId),
+ );
+
+ return {
+ project: data?.success ? data.data.project : null,
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching all runners
+export function useRunners() {
+ const { data, error, mutate, isLoading } = useSWR("runners", () =>
+ GetRunners(),
+ );
+
+ return {
+ runners: data?.success ? data.data.runners : [],
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching running executions
+export function useRunningExecutions() {
+ const { data, error, mutate, isLoading } = useSWR("running-executions", () =>
+ GetRunningExecutions(),
+ );
+
+ return {
+ runningExecutions: data?.success ? data.data : [],
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching user stats
+export function useUserStats() {
+ const { data, error, mutate, isLoading } = useSWR("user-stats", () =>
+ GetUserStats(),
+ );
+
+ return {
+ stats: data?.success ? data.data.stats : null,
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching executions with attention
+export function useExecutionsWithAttention() {
+ const { data, error, mutate, isLoading } = useSWR(
+ "executions-with-attention",
+ () => GetExecutionsWithAttention(),
+ );
+
+ return {
+ executionsWithAttention: data?.success ? data.data.executions : [],
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching project audit logs
+export function useProjectAuditLogs(projectId: string) {
+ const { data, error, mutate, isLoading } = useSWR(
+ projectId ? `project-audit-${projectId}` : null,
+ () => GetProjectAuditLogs(projectId),
+ );
+
+ return {
+ audit: data?.success ? data.data.audit : [],
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching project API keys
+export function useProjectApiKeys(projectId: string) {
+ const { data, error, mutate, isLoading } = useSWR(
+ projectId ? `project-tokens-${projectId}` : null,
+ () => GetProjectApiKeys(projectId),
+ );
+
+ return {
+ tokens: data?.success ? data.data.tokens : [],
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching a single execution
+export function useExecution(executionId: string) {
+ const { data, error, mutate, isLoading } = useSWR(
+ executionId ? `execution-${executionId}` : null,
+ () => GetExecution(executionId),
+ );
+
+ return {
+ execution: data?.success ? data.data.execution : null,
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
diff --git a/services/frontend/lib/swr/hooks/useRefreshCache.ts b/services/frontend/lib/swr/hooks/useRefreshCache.ts
new file mode 100644
index 00000000..356995fa
--- /dev/null
+++ b/services/frontend/lib/swr/hooks/useRefreshCache.ts
@@ -0,0 +1,80 @@
+import { mutate } from "swr";
+
+/**
+ * Custom hook that provides SWR cache refresh functions for different data types
+ * Use this in modals instead of router.refresh() to update SWR cache after mutations
+ *
+ * This approach uses direct cache key mutations instead of importing all hooks
+ * to avoid potential circular dependencies and bundle size issues.
+ */
+export function useRefreshCache() {
+ return {
+ // Direct cache key refreshes
+ refreshFlows: () => mutate("flows"),
+ refreshProjects: () => mutate("projects"),
+ refreshFolders: () => mutate("folders"),
+ refreshRunners: () => mutate("runners"),
+ refreshUser: () => mutate("user-details"),
+ refreshUserStats: () => mutate("user-stats"),
+ refreshExecutionsWithAttention: () => mutate("executions-with-attention"),
+ refreshRunningExecutions: () => mutate("running-executions"),
+ refreshPageSettings: () => mutate("page-settings"),
+
+ // Specific entity refreshes
+ refreshFlow: (flowId: string) => mutate(`flow-${flowId}`),
+ refreshFlowExecutions: (flowId: string) =>
+ mutate(`flow-executions-${flowId}`),
+ refreshProject: (projectId: string) => mutate(`project-${projectId}`),
+ refreshProjectRunners: (projectId: string) =>
+ mutate(`project-runners-${projectId}`),
+ refreshProjectAudit: (projectId: string) =>
+ mutate(`project-audit-${projectId}`),
+ refreshProjectTokens: (projectId: string) =>
+ mutate(`project-tokens-${projectId}`),
+ refreshExecution: (executionId: string) =>
+ mutate(`execution-${executionId}`),
+ refreshFolder: (folderId: string) => mutate(`folder-${folderId}`),
+ refreshFolderExecutions: (folderId: string) =>
+ mutate(`folder-executions-${folderId}`),
+
+ // Convenience methods for common combinations
+ refreshAll: () => {
+ mutate("flows");
+ mutate("projects");
+ mutate("folders");
+ mutate("runners");
+ mutate("user-details");
+ mutate("user-stats");
+ mutate("executions-with-attention");
+ mutate("running-executions");
+ mutate("page-settings");
+ },
+
+ refreshProjectData: () => {
+ mutate("projects");
+ mutate("flows");
+ mutate("folders");
+ mutate("runners");
+ },
+
+ refreshFlowData: (flowId?: string) => {
+ mutate("flows");
+ mutate("running-executions");
+ mutate("executions-with-attention");
+ if (flowId) {
+ mutate(`flow-${flowId}`);
+ mutate(`flow-executions-${flowId}`);
+ }
+ },
+
+ refreshAllFlowData: (flowId?: string) => {
+ mutate("flows");
+ mutate("running-executions");
+ mutate("executions-with-attention");
+ if (flowId) {
+ mutate(`flow-${flowId}`);
+ mutate(`flow-executions-${flowId}`);
+ }
+ },
+ };
+}
diff --git a/services/frontend/lib/swr/provider.tsx b/services/frontend/lib/swr/provider.tsx
new file mode 100644
index 00000000..8d710cbc
--- /dev/null
+++ b/services/frontend/lib/swr/provider.tsx
@@ -0,0 +1,29 @@
+"use client";
+
+import { SWRConfig } from "swr";
+import { ReactNode } from "react";
+
+interface SWRProviderProps {
+ children: ReactNode;
+}
+
+export default function SWRProvider({ children }: SWRProviderProps) {
+ return (
+ {
+ // Handle SWR errors silently in production
+ // You could send to an error reporting service here
+ },
+ }}
+ >
+ {children}
+
+ );
+}
diff --git a/services/frontend/package.json b/services/frontend/package.json
index 7d1a67cb..f5bd347e 100644
--- a/services/frontend/package.json
+++ b/services/frontend/package.json
@@ -84,6 +84,7 @@
"react-timeago": "^7.2.0",
"recharts": "2.15.1",
"scroll-into-view-if-needed": "^3.1.0",
+ "swr": "^2.3.4",
"tailwind-merge": "^2.6.0",
"tailwind-variants": "1.0.0",
"tailwindcss": "3.4.17",
diff --git a/services/frontend/pnpm-lock.yaml b/services/frontend/pnpm-lock.yaml
index 822062e6..1c7a014a 100644
--- a/services/frontend/pnpm-lock.yaml
+++ b/services/frontend/pnpm-lock.yaml
@@ -230,6 +230,9 @@ importers:
scroll-into-view-if-needed:
specifier: ^3.1.0
version: 3.1.0
+ swr:
+ specifier: ^2.3.4
+ version: 2.3.4(react@19.0.0)
tailwind-merge:
specifier: ^2.6.0
version: 2.6.0
@@ -6729,6 +6732,11 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
+ swr@2.3.4:
+ resolution: {integrity: sha512-bYd2lrhc+VarcpkgWclcUi92wYCpOgMws9Sd1hG1ntAu0NEy+14CbotuFjshBU2kt9rYj9TSmDcybpxpeTU1fg==}
+ peerDependencies:
+ react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
synckit@0.10.3:
resolution: {integrity: sha512-R1urvuyiTaWfeCggqEvpDJwAlDVdsT9NM+IP//Tk2x7qHCkSvBk/fwFgw/TLAHzZlrAnnazMcRw0ZD8HlYFTEQ==}
engines: {node: ^14.18.0 || >=16.0.0}
@@ -15812,6 +15820,12 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
+ swr@2.3.4(react@19.0.0):
+ dependencies:
+ dequal: 2.0.3
+ react: 19.0.0
+ use-sync-external-store: 1.5.0(react@19.0.0)
+
synckit@0.10.3:
dependencies:
'@pkgr/core': 0.2.0
From 6f8c14420c2893bd40c5785f19bdbf40bc970fdb Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Tue, 19 Aug 2025 14:31:37 +0200
Subject: [PATCH 12/45] Refactor execution and flow components to utilize SWR
for data fetching and cache management
- Replaced direct API calls with SWR hooks in execution and flow components for better data management.
- Implemented auto-refresh for running executions using SWR's refreshInterval feature.
- Removed the Reloader component and integrated refresh functionality directly into relevant components.
- Enhanced cache refreshing logic to ensure all related data is updated after actions like add, edit, and delete.
- Updated the useRefreshCache hook to include methods for refreshing execution and flow data.
- Adjusted pagination and filtering logic to work seamlessly with the new SWR setup.
---
.../frontend/components/dashboard/home.tsx | 14 +-
.../execution/adminExecutionActions.tsx | 6 +-
.../executions/execution/adminStepActions.tsx | 6 +-
.../executions/execution/execution.tsx | 67 +++++++---
.../execution/executionStepsAccordion.tsx | 25 ++--
.../execution/executionStepsTable.tsx | 9 +-
.../components/executions/executions.tsx | 122 +++++++-----------
.../executions/executionsCompact.tsx | 2 +-
.../components/flows/flow/heading.tsx | 26 +---
.../components/modals/actions/add.tsx | 9 +-
.../components/modals/actions/copy.tsx | 9 +-
.../components/modals/actions/delete.tsx | 8 +-
.../components/modals/actions/edit.tsx | 8 +-
.../components/modals/actions/editDetails.tsx | 6 +-
.../components/modals/actions/upgrade.tsx | 8 +-
.../components/modals/executions/delete.tsx | 8 +-
.../components/modals/executions/schedule.tsx | 6 +-
.../modals/failurePipelines/create.tsx | 6 +-
.../modals/failurePipelines/delete.tsx | 6 +-
.../modals/failurePipelines/edit.tsx | 6 +-
.../frontend/components/projects/project.tsx | 4 -
.../frontend/components/reloader/Reloader.tsx | 39 ------
.../frontend/components/runners/heading.tsx | 5 -
services/frontend/lib/swr/hooks/flows.ts | 68 ++++++++++
.../frontend/lib/swr/hooks/useRefreshCache.ts | 46 +++++++
services/frontend/lib/swr/provider.tsx | 2 +-
26 files changed, 286 insertions(+), 235 deletions(-)
delete mode 100644 services/frontend/components/reloader/Reloader.tsx
diff --git a/services/frontend/components/dashboard/home.tsx b/services/frontend/components/dashboard/home.tsx
index 21271839..3c947f7d 100644
--- a/services/frontend/components/dashboard/home.tsx
+++ b/services/frontend/components/dashboard/home.tsx
@@ -18,7 +18,6 @@ import ReactTimeago from "react-timeago";
import WelcomeModal from "@/components/modals/user/welcome";
import Stats from "@/components/dashboard/stats";
-import Reloader from "../reloader/Reloader";
import Executions from "../executions/executions";
export default function DashboardHome({
@@ -66,14 +65,11 @@ export default function DashboardHome({
return (
-
-
-
Hello, {user.username} 👋
-
- Here's the current status for today.
-
-
-
+
+
Hello, {user.username} 👋
+
+ Here's the current status for today.
+
diff --git a/services/frontend/components/executions/execution/adminExecutionActions.tsx b/services/frontend/components/executions/execution/adminExecutionActions.tsx
index 8ac20d0f..fe406aeb 100644
--- a/services/frontend/components/executions/execution/adminExecutionActions.tsx
+++ b/services/frontend/components/executions/execution/adminExecutionActions.tsx
@@ -8,16 +8,16 @@ import {
DropdownSection,
DropdownTrigger,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import UpdateExecution from "@/lib/fetch/executions/PUT/update";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function AdminExecutionActions({
execution,
}: {
execution: any;
}) {
- const router = useRouter();
+ const { refreshExecution } = useRefreshCache();
async function changeExecutionStatus(status: string) {
const newExecution = { ...execution };
@@ -106,7 +106,7 @@ export default function AdminExecutionActions({
color: "success",
variant: "flat",
});
- router.refresh();
+ refreshExecution(execution.id);
} else {
addToast({
title: "Execution",
diff --git a/services/frontend/components/executions/execution/adminStepActions.tsx b/services/frontend/components/executions/execution/adminStepActions.tsx
index 1a463401..c60c0638 100644
--- a/services/frontend/components/executions/execution/adminStepActions.tsx
+++ b/services/frontend/components/executions/execution/adminStepActions.tsx
@@ -8,9 +8,9 @@ import {
DropdownSection,
DropdownTrigger,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import UpdateExecutionStep from "@/lib/fetch/executions/PUT/updateStep";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function AdminStepActions({
execution,
@@ -19,7 +19,7 @@ export default function AdminStepActions({
execution: any;
step: any;
}) {
- const router = useRouter();
+ const { refreshExecutionSteps } = useRefreshCache();
async function changeStepStatus(status: string) {
const newStep = { ...step };
@@ -317,7 +317,7 @@ export default function AdminStepActions({
color: "success",
variant: "flat",
});
- router.refresh();
+ refreshExecutionSteps(execution.id);
} else {
addToast({
title: "Execution",
diff --git a/services/frontend/components/executions/execution/execution.tsx b/services/frontend/components/executions/execution/execution.tsx
index ce26b152..0263d446 100644
--- a/services/frontend/components/executions/execution/execution.tsx
+++ b/services/frontend/components/executions/execution/execution.tsx
@@ -3,12 +3,13 @@
import { Icon } from "@iconify/react";
import { addToast, Button, ButtonGroup, Divider, Spacer } from "@heroui/react";
import { useRouter } from "next/navigation";
-import React, { useEffect, useState } from "react";
+import React, { useState } from "react";
-import Reloader from "@/components/reloader/Reloader";
-import GetExecutionSteps from "@/lib/fetch/executions/steps";
+import { useExecutionSteps } from "@/lib/swr/hooks/flows";
import APICancelExecution from "@/lib/fetch/executions/cancel";
import { useExecutionStepStyleStore } from "@/lib/functions/userExecutionStepStyle";
+import RefreshButton from "@/components/ui/refresh-button";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
import AdminExecutionActions from "./adminExecutionActions";
import ExecutionDetails from "./details";
@@ -19,24 +20,38 @@ export function Execution({ flow, execution, runners, userDetails }: any) {
const router = useRouter();
const { displayStyle, setDisplayStyle } = useExecutionStepStyleStore();
- const [steps, setSteps] = useState([] as any);
- useEffect(() => {
- GetExecutionSteps(execution.id).then((steps) => {
- if (steps.success) {
- setSteps(steps.data.steps);
- } else {
- if ("error" in steps) {
- addToast({
- title: "Execution",
- description: steps.error,
- color: "danger",
- variant: "flat",
- });
- }
- }
- });
- }, [execution]);
+ // Check if execution is running to enable auto-refresh
+ const isRunning =
+ execution.status === "running" ||
+ execution.status === "pending" ||
+ execution.status === "paused" ||
+ execution.status === "scheduled" ||
+ execution.status === "interactionWaiting";
+
+ // Use SWR for auto-refreshing execution steps data
+ const { steps, isError } = useExecutionSteps(execution.id, isRunning);
+ const { refreshExecution, refreshExecutionSteps } = useRefreshCache();
+ const [executionLoading, setExecutionLoading] = useState(false);
+
+ // Handle SWR errors
+ React.useEffect(() => {
+ if (isError) {
+ addToast({
+ title: "Error fetching execution steps",
+ description: "Failed to load execution steps. Please try refreshing.",
+ color: "danger",
+ variant: "flat",
+ });
+ }
+ }, [isError]);
+
+ const handleRefresh = async () => {
+ setExecutionLoading(true);
+ await refreshExecution(execution.id);
+ await refreshExecutionSteps(execution.id);
+ setExecutionLoading(false);
+ };
return (
<>
@@ -114,7 +129,17 @@ export function Execution({ flow, execution, runners, userDetails }: any) {
execution.status === "interactionWaiting") && (
-
+ {isRunning && (
+
+
+ Auto-refresh 2s
+
+ )}
+
)}
diff --git a/services/frontend/components/executions/execution/executionStepsAccordion.tsx b/services/frontend/components/executions/execution/executionStepsAccordion.tsx
index 2874bf58..7fb65f2e 100644
--- a/services/frontend/components/executions/execution/executionStepsAccordion.tsx
+++ b/services/frontend/components/executions/execution/executionStepsAccordion.tsx
@@ -11,12 +11,12 @@ import {
Progress,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useEffect, useState, useRef } from "react";
import { isMobile, isTablet } from "react-device-detect";
import InteractExecutionStep from "@/lib/fetch/executions/PUT/step_interact";
import { executionStatusWrapper } from "@/lib/functions/executionStyles";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
import AdminStepActions from "./adminStepActions";
@@ -27,7 +27,7 @@ export function ExecutionStepsAccordion({
runners,
userDetails,
}: any) {
- const router = useRouter();
+ const { refreshExecution, refreshExecutionSteps } = useRefreshCache();
const [parSteps, setParSteps] = useState([] as any);
const [selectedKeys, setSelectedKeys] = React.useState(new Set(["1"]));
@@ -98,19 +98,19 @@ export function ExecutionStepsAccordion({
(step: any) => step.status !== "pending",
);
const activeStep = nonPendingSteps[nonPendingSteps.length - 1];
-
+
if (activeStep) {
const stepElement = stepItemRef.current[activeStep.id];
if (stepElement) {
// Set flag to prevent scroll listener from interfering
isAutoScrollingRef.current = true;
-
+
stepElement.scrollIntoView({
behavior: "smooth",
block: "center",
});
-
+
// Clear the flag after scrolling is complete
setTimeout(() => {
isAutoScrollingRef.current = false;
@@ -248,22 +248,22 @@ export function ExecutionStepsAccordion({
(step: any) => step.status !== "pending",
);
const activeStep = nonPendingSteps[nonPendingSteps.length - 1];
-
+
if (activeStep) {
const stepElement = stepItemRef.current[activeStep.id];
if (stepElement) {
// Set flag to prevent scroll listener from interfering
isAutoScrollingRef.current = true;
-
+
stepElement.scrollIntoView({
behavior: "smooth",
block: "center",
});
-
+
setStepAutoScrollEnabled(true);
setUserSelected(false);
-
+
// Clear the flag after scrolling is complete
setTimeout(() => {
isAutoScrollingRef.current = false;
@@ -338,7 +338,10 @@ export function ExecutionStepsAccordion({
color: "success",
variant: "flat",
});
- router.refresh();
+ // wait 1 second
+ await new Promise((resolve) => setTimeout(resolve, 1000));
+ await refreshExecutionSteps(execution.id);
+ await refreshExecution(execution.id);
}
}
@@ -623,7 +626,7 @@ export function ExecutionStepsAccordion({
-
+
{/* Floating auto-scroll button - fixed position */}
{!stepAutoScrollEnabled && (
({});
@@ -328,7 +328,10 @@ export function ExecutionStepsTable({
variant: "flat",
});
setPageAutoScrollEnabled(true);
- router.refresh();
+ // wait 1 second
+ await new Promise((resolve) => setTimeout(resolve, 1000));
+ await refreshExecutionSteps(execution.id);
+ await refreshExecution(execution.id);
}
}
diff --git a/services/frontend/components/executions/executions.tsx b/services/frontend/components/executions/executions.tsx
index 1d248631..c4585d45 100644
--- a/services/frontend/components/executions/executions.tsx
+++ b/services/frontend/components/executions/executions.tsx
@@ -13,8 +13,7 @@ import {
Tooltip,
} from "@heroui/react";
import { Icon } from "@iconify/react";
-import { useEffect, useMemo, useState } from "react";
-import { useRouter } from "next/navigation";
+import { useMemo, useState } from "react";
import { useExecutionsStyleStore } from "@/lib/functions/userExecutionsStyle";
import {
@@ -23,8 +22,10 @@ import {
executionStatusIcon,
executionStatusName,
} from "@/lib/functions/executionStyles";
-import GetExecutions from "@/lib/fetch/executions/all";
-import GetFlowExecutions from "@/lib/fetch/flow/executions";
+import {
+ useExecutions,
+ useFlowExecutionsPaginated,
+} from "@/lib/swr/hooks/flows";
import ExecutionsList from "./executionsList";
import ExecutionsTable from "./executionsTable";
@@ -37,85 +38,55 @@ export default function Executions({
flows,
flowID,
}: any) {
- const router = useRouter();
-
const { displayStyle, setDisplayStyle } = useExecutionsStyleStore();
const [statusFilter, setStatusFilter] = useState(new Set([]) as any);
- const [loading, setLoading] = useState(true);
- const [totalExecutions, setTotalExecutions] = useState(0);
- const [executions, setExecutions] = useState([] as any);
- const [refreshKey, setRefreshKey] = useState(0);
-
// pagination
const [page, setPage] = useState(1);
const limit =
displayStyle === "list" ? 4 : displayStyle === "compact" ? 6 : 10;
- const offset = (page - 1) * limit;
-
- const items = useMemo(() => {
- return executions;
- }, [executions]);
-
- useEffect(() => {
- setLoading(true);
- // Clear executions when changing pages to avoid showing stale data
- setExecutions([]);
- async function fetchExecutions() {
- let res: any;
-
- if (flowID) {
- res = await GetFlowExecutions(
- flowID,
- limit,
- offset,
- statusFilter.size > 0 ? Array.from(statusFilter).join(",") : null,
- );
- } else {
- res = await GetExecutions(
- limit,
- offset,
- statusFilter.size > 0 ? Array.from(statusFilter).join(",") : null,
- );
- }
-
- if (res.success) {
- setLoading(false);
- setExecutions(res.data.executions);
- setTotalExecutions(res.data.total);
- }
- }
- fetchExecutions();
- }, [page, statusFilter, displayStyle, refreshKey]);
+ // Calculate offset using page directly for now (will be validated later)
+ const offset = (page - 1) * limit;
- useEffect(() => {
- // Only auto-refresh when on page 1 with no filters to avoid interrupting user navigation
- const shouldAutoRefresh = page === 1 && statusFilter.size === 0;
+ // Convert statusFilter to string for API
+ const statusFilterString =
+ statusFilter.size > 0 ? Array.from(statusFilter).join(",") : null;
- if (!shouldAutoRefresh) return;
+ // Always call both hooks but only use the relevant one
+ const flowExecutionsResult = useFlowExecutionsPaginated(
+ flowID || null,
+ limit,
+ offset,
+ statusFilterString,
+ );
+ const allExecutionsResult = useExecutions(
+ flowID ? 0 : limit,
+ flowID ? 0 : offset,
+ flowID ? null : statusFilterString,
+ );
- const interval = setInterval(async () => {
- // Background fetch without loading state to avoid disabling pagination
- let res: any;
+ // Choose the right result based on whether we have a flowID
+ const {
+ executions,
+ total: totalExecutions,
+ isLoading: loading,
+ refresh,
+ } = flowID ? flowExecutionsResult : allExecutionsResult;
- if (flowID) {
- res = await GetFlowExecutions(flowID, limit, offset, null);
- } else {
- res = await GetExecutions(limit, offset, null);
- }
+ const items = useMemo(() => {
+ return executions || [];
+ }, [executions]);
- if (res.success) {
- setExecutions(res.data.executions);
- setTotalExecutions(res.data.total);
- }
- }, 5000);
+ // Calculate total pages
+ const totalPages = Math.max(1, Math.ceil(totalExecutions / limit));
- return () => clearInterval(interval);
- }, [page, statusFilter, flowID, limit, offset]);
+ // Ensure page is never higher than total pages
+ const safePage = Math.min(page, totalPages);
- function pages() {
- return Math.ceil(totalExecutions / limit);
+ // If safe page is different from current page, update it
+ if (safePage !== page && totalPages > 0 && !loading) {
+ setPage(safePage);
}
return (
@@ -168,14 +139,14 @@ export default function Executions({
}
variant="flat"
onPress={() => {
- setRefreshKey((k) => k + 1);
- router.refresh();
+ refresh();
}}
>
Refresh
@@ -194,6 +165,7 @@ export default function Executions({
variant={displayStyle === "compact" ? "solid" : "flat"}
onPress={() => {
setDisplayStyle("compact");
+ setPage(1);
}}
/>
@@ -204,6 +176,7 @@ export default function Executions({
variant={displayStyle === "list" ? "solid" : "flat"}
onPress={() => {
setDisplayStyle("list");
+ setPage(1);
}}
/>
@@ -216,6 +189,7 @@ export default function Executions({
variant={displayStyle === "table" ? "solid" : "flat"}
onPress={() => {
setDisplayStyle("table");
+ setPage(1);
}}
/>
@@ -265,10 +239,10 @@ export default function Executions({
setPage(page)}
+ isDisabled={loading}
+ page={safePage}
+ total={totalPages}
+ onChange={(newPage) => setPage(newPage)}
/>
diff --git a/services/frontend/components/executions/executionsCompact.tsx b/services/frontend/components/executions/executionsCompact.tsx
index 18840696..43bab86f 100644
--- a/services/frontend/components/executions/executionsCompact.tsx
+++ b/services/frontend/components/executions/executionsCompact.tsx
@@ -201,7 +201,7 @@ export default function ExecutionsCompact({
>
{execution.steps.map((step, index) => (
diff --git a/services/frontend/components/flows/flow/heading.tsx b/services/frontend/components/flows/flow/heading.tsx
index 6ef41c97..6c76e35c 100644
--- a/services/frontend/components/flows/flow/heading.tsx
+++ b/services/frontend/components/flows/flow/heading.tsx
@@ -6,9 +6,8 @@ import { Icon } from "@iconify/react";
import ScheduleExecutionModal from "@/components/modals/executions/schedule";
import EditFlowModal from "@/components/modals/flows/edit";
import canEditProject from "@/lib/functions/canEditProject";
-import RefreshButton from "@/components/ui/refresh-button";
import { startExecution } from "@/lib/swr/api/executions";
-import { useFlowExecutions } from "@/lib/swr/hooks/flows";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function FlowHeading({
flow,
@@ -27,10 +26,7 @@ export default function FlowHeading({
}) {
const editFlowModal = useDisclosure();
const scheduleExecutionModal = useDisclosure();
-
- // Use SWR for auto-refreshing flow executions data
- const { refresh: refreshExecutions, isLoading: executionsLoading } =
- useFlowExecutions(flow.id);
+ const { refreshAllExecutionCaches } = useRefreshCache();
const handleExecuteFlow = async () => {
const result = await startExecution(flow.id);
@@ -41,7 +37,7 @@ export default function FlowHeading({
color: "success",
});
// Immediately refresh executions data
- refreshExecutions();
+ refreshAllExecutionCaches(flow.id);
} else {
addToast({
title: "Execution start failed",
@@ -51,10 +47,6 @@ export default function FlowHeading({
}
};
- const handleRefresh = async () => {
- await refreshExecutions();
- };
-
return (
@@ -105,12 +97,6 @@ export default function FlowHeading({
>
Edit
-
-
{/* Mobile */}
@@ -132,12 +118,6 @@ export default function FlowHeading({
onPress={handleExecuteFlow}
/>
-
{
const { children, ...otherProps } = props;
@@ -72,7 +72,7 @@ export default function AddActionModal({
isFailurePipeline?: boolean;
failurePipeline?: any;
}) {
- const router = useRouter();
+ const { refreshFlowData } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
@@ -404,7 +404,7 @@ export default function AddActionModal({
});
setCurrentStep(0);
onOpenChange();
- router.refresh();
+ refreshFlowData(flow.id); // Refresh SWR cache with specific flow ID
addToast({
title: "Flow",
description: "Action added successfully",
@@ -412,6 +412,7 @@ export default function AddActionModal({
variant: "flat",
});
} else {
+ refreshFlowData(flow.id); // Refresh SWR cache with specific flow ID
setError(true);
setErrorText(res.error);
setErrorMessage(res.message);
@@ -517,7 +518,7 @@ export default function AddActionModal({
});
setCurrentStep(0);
onOpenChange();
- router.refresh();
+ refreshFlowData(flow.id); // Refresh SWR cache with specific flow ID
addToast({
title: "Flow",
description: "Action added successfully to failure pipeline",
diff --git a/services/frontend/components/modals/actions/copy.tsx b/services/frontend/components/modals/actions/copy.tsx
index 15408d4e..d3e65ed2 100644
--- a/services/frontend/components/modals/actions/copy.tsx
+++ b/services/frontend/components/modals/actions/copy.tsx
@@ -23,7 +23,6 @@ import {
Spacer,
Textarea,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";
import { v4 as uuidv4 } from "uuid";
@@ -32,6 +31,7 @@ import ErrorCard from "@/components/error/ErrorCard";
import AddFlowActions from "@/lib/fetch/flow/POST/AddFlowActions";
import AddFlowFailurePipelineActions from "@/lib/fetch/flow/POST/AddFlowFailurePipelineActions";
import MinimalRowSteps from "@/components/steps/minimal-row-steps";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export const CustomRadio = (props: any) => {
const { children, ...otherProps } = props;
@@ -66,8 +66,8 @@ export default function CopyActionModal({
isFailurePipeline?: boolean;
failurePipeline?: any;
}) {
- const router = useRouter();
const { isOpen, onOpenChange } = disclosure;
+ const { refreshFlowData } = useRefreshCache();
const [steps] = useState(3);
const [currentStep, setCurrentStep] = useState(0);
@@ -211,7 +211,7 @@ export default function CopyActionModal({
});
setCurrentStep(0);
onOpenChange();
- router.refresh();
+ refreshFlowData(flow.id); // Refresh SWR cache instead of router
} else {
setError(true);
setErrorText(res.error);
@@ -297,8 +297,9 @@ export default function CopyActionModal({
});
setCurrentStep(0);
onOpenChange();
- router.refresh();
+ refreshFlowData(flow.id); // Refresh SWR cache instead of router
} else {
+ refreshFlowData(flow.id); // Refresh SWR cache instead of router
setError(true);
setErrorText(res.error);
setErrorMessage(res.message);
diff --git a/services/frontend/components/modals/actions/delete.tsx b/services/frontend/components/modals/actions/delete.tsx
index 7750a307..3a285705 100644
--- a/services/frontend/components/modals/actions/delete.tsx
+++ b/services/frontend/components/modals/actions/delete.tsx
@@ -10,13 +10,13 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import { Icon } from "@iconify/react";
import DeleteAction from "@/lib/fetch/flow/DELETE/DeleteAction";
import ErrorCard from "@/components/error/ErrorCard";
import DeleteFailurePipelineAction from "@/lib/fetch/flow/DELETE/DeleteFailurePipelineAction";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function DeleteActionModal({
disclosure,
@@ -31,7 +31,7 @@ export default function DeleteActionModal({
isFailurePipeline?: boolean;
failurePipeline?: any;
}) {
- const router = useRouter();
+ const { refreshFlowData } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
@@ -64,7 +64,7 @@ export default function DeleteActionModal({
color: "success",
variant: "flat",
});
- router.refresh();
+ refreshFlowData(flowID); // Refresh SWR cache with specific flow ID
} else {
setIsDeleteLoading(false);
setError(true);
@@ -110,7 +110,7 @@ export default function DeleteActionModal({
color: "success",
variant: "flat",
});
- router.refresh();
+ refreshFlowData(flowID); // Refresh SWR cache with specific flow ID
} else {
setIsDeleteLoading(false);
setError(true);
diff --git a/services/frontend/components/modals/actions/edit.tsx b/services/frontend/components/modals/actions/edit.tsx
index 27a0465b..c2e6aed6 100644
--- a/services/frontend/components/modals/actions/edit.tsx
+++ b/services/frontend/components/modals/actions/edit.tsx
@@ -23,7 +23,6 @@ import {
Spacer,
Textarea,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";
import UpdateFlowActions from "@/lib/fetch/flow/PUT/UpdateActions";
@@ -31,6 +30,7 @@ import { cn } from "@/components/cn/cn";
import ErrorCard from "@/components/error/ErrorCard";
import UpdateFlowFailurePipelineActions from "@/lib/fetch/flow/PUT/UpdateFailurePipelineActions";
import MinimalRowSteps from "@/components/steps/minimal-row-steps";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export const CustomRadio = (props: any) => {
const { children, ...otherProps } = props;
@@ -65,8 +65,8 @@ export default function EditActionModal({
isFailurePipeline?: boolean;
failurePipeline?: any;
}) {
- const router = useRouter();
const { isOpen, onOpenChange } = disclosure;
+ const { refreshFlowData } = useRefreshCache();
const [steps] = useState(3);
const [currentStep, setCurrentStep] = useState(0);
@@ -202,7 +202,7 @@ export default function EditActionModal({
});
setCurrentStep(0);
onOpenChange();
- router.refresh();
+ refreshFlowData(flow.id); // Refresh SWR cache with specific flow ID
} else {
setError(true);
setErrorText(res.error);
@@ -269,7 +269,7 @@ export default function EditActionModal({
variant: "flat",
});
onOpenChange();
- router.refresh();
+ refreshFlowData(flow.id); // Refresh SWR cache with specific flow ID
} else {
setError(true);
setErrorText(res.error);
diff --git a/services/frontend/components/modals/actions/editDetails.tsx b/services/frontend/components/modals/actions/editDetails.tsx
index d50017ba..eb982a35 100644
--- a/services/frontend/components/modals/actions/editDetails.tsx
+++ b/services/frontend/components/modals/actions/editDetails.tsx
@@ -18,12 +18,12 @@ import {
Spacer,
Tooltip,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";
import UpdateFlowActionsDetails from "@/lib/fetch/flow/PUT/UpdateActionsDetails";
import { cn } from "@/components/cn/cn";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export const CustomRadio = (props: any) => {
const { children, ...otherProps } = props;
@@ -51,8 +51,8 @@ export default function EditFlowActionsDetails({
disclosure: UseDisclosureReturn;
flow: any;
}) {
- const router = useRouter();
const { isOpen, onOpenChange } = disclosure;
+ const { refreshFlowData } = useRefreshCache();
const [isLoading, setLoading] = useState(false);
const [encryptedActionParams, setEncryptedActionParams] = useState(true);
@@ -95,7 +95,7 @@ export default function EditFlowActionsDetails({
setError(false);
setErrorText("");
setErrorMessage("");
- router.refresh();
+ refreshFlowData(flow.id); // Refresh SWR cache instead of router
addToast({
title: "Flow",
description: "Flow Actions Details updated successfully",
diff --git a/services/frontend/components/modals/actions/upgrade.tsx b/services/frontend/components/modals/actions/upgrade.tsx
index 9b664735..1586cd72 100644
--- a/services/frontend/components/modals/actions/upgrade.tsx
+++ b/services/frontend/components/modals/actions/upgrade.tsx
@@ -21,13 +21,13 @@ import {
Spacer,
Textarea,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";
import UpdateFlowActions from "@/lib/fetch/flow/PUT/UpdateActions";
import { cn } from "@/components/cn/cn";
import ErrorCard from "@/components/error/ErrorCard";
import UpdateFlowFailurePipelineActions from "@/lib/fetch/flow/PUT/UpdateFailurePipelineActions";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export const CustomRadio = (props: any) => {
const { children, ...otherProps } = props;
@@ -64,8 +64,8 @@ export default function UpgradeActionModal({
isFailurePipeline?: boolean;
failurePipeline?: any;
}) {
- const router = useRouter();
const { isOpen, onOpenChange } = disclosure;
+ const { refreshFlowData } = useRefreshCache();
const [isLoading, setLoading] = useState(false);
@@ -209,7 +209,7 @@ export default function UpgradeActionModal({
variant: "flat",
});
onOpenChange();
- router.refresh();
+ refreshFlowData(flow.id); // Refresh SWR cache instead of router
} else {
setError(true);
setErrorText(res.error);
@@ -281,7 +281,7 @@ export default function UpgradeActionModal({
variant: "flat",
});
onOpenChange();
- router.refresh();
+ refreshFlowData(flow.id); // Refresh SWR cache instead of router
} else {
setError(true);
setErrorText(res.error);
diff --git a/services/frontend/components/modals/executions/delete.tsx b/services/frontend/components/modals/executions/delete.tsx
index 0208eb45..a9cadc55 100644
--- a/services/frontend/components/modals/executions/delete.tsx
+++ b/services/frontend/components/modals/executions/delete.tsx
@@ -10,12 +10,12 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import { Icon } from "@iconify/react";
import DeleteExecution from "@/lib/fetch/executions/DELETE/delete";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function DeleteExecutionModal({
disclosure,
@@ -24,7 +24,7 @@ export default function DeleteExecutionModal({
disclosure: UseDisclosureReturn;
execution: any;
}) {
- const router = useRouter();
+ const { refreshAllExecutionCaches } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
@@ -57,7 +57,9 @@ export default function DeleteExecutionModal({
color: "success",
variant: "flat",
});
- router.refresh();
+
+ // Refresh all execution-related SWR caches
+ refreshAllExecutionCaches(execution.flow_id);
} else {
setError(true);
setErrorText(res.error);
diff --git a/services/frontend/components/modals/executions/schedule.tsx b/services/frontend/components/modals/executions/schedule.tsx
index 114785c3..54745699 100644
--- a/services/frontend/components/modals/executions/schedule.tsx
+++ b/services/frontend/components/modals/executions/schedule.tsx
@@ -17,12 +17,12 @@ import {
Spacer,
TimeInput,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import { Icon } from "@iconify/react";
import ErrorCard from "@/components/error/ErrorCard";
import APIScheduleExecution from "@/lib/fetch/executions/schedule";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function ScheduleExecutionModal({
disclosure,
@@ -31,7 +31,7 @@ export default function ScheduleExecutionModal({
disclosure: UseDisclosureReturn;
flow: any;
}) {
- const router = useRouter();
+ const { refreshAllExecutionCaches } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
@@ -71,7 +71,7 @@ export default function ScheduleExecutionModal({
color: "success",
variant: "flat",
});
- router.refresh();
+ refreshAllExecutionCaches(flow.id);
} else {
setError(true);
setErrorText(res.error);
diff --git a/services/frontend/components/modals/failurePipelines/create.tsx b/services/frontend/components/modals/failurePipelines/create.tsx
index 50e2f920..a02f988e 100644
--- a/services/frontend/components/modals/failurePipelines/create.tsx
+++ b/services/frontend/components/modals/failurePipelines/create.tsx
@@ -14,12 +14,12 @@ import {
Select,
SelectItem,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useState } from "react";
import { Icon } from "@iconify/react";
import ErrorCard from "@/components/error/ErrorCard";
import CreateFlowFailurePipeline from "@/lib/fetch/flow/POST/AddFlowFailurePipeline";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function CreateFailurePipelineModal({
flow,
@@ -28,7 +28,7 @@ export default function CreateFailurePipelineModal({
flow: any;
disclosure: UseDisclosureReturn;
}) {
- const router = useRouter();
+ const { refreshFlowData } = useRefreshCache();
// create modal
const { isOpen, onOpenChange } = disclosure;
@@ -69,7 +69,7 @@ export default function CreateFailurePipelineModal({
}
if (response.success) {
- router.refresh();
+ refreshFlowData(flow.id); // Refresh SWR cache with specific flow ID
onOpenChange();
setName("");
setError(false);
diff --git a/services/frontend/components/modals/failurePipelines/delete.tsx b/services/frontend/components/modals/failurePipelines/delete.tsx
index 61525587..eb09f8f7 100644
--- a/services/frontend/components/modals/failurePipelines/delete.tsx
+++ b/services/frontend/components/modals/failurePipelines/delete.tsx
@@ -10,12 +10,12 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import { Icon } from "@iconify/react";
import ErrorCard from "@/components/error/ErrorCard";
import DeleteFlowFailurePipeline from "@/lib/fetch/flow/DELETE/DeleteFailurePipeline";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function DeleteFailurePipelineModal({
disclosure,
@@ -26,7 +26,7 @@ export default function DeleteFailurePipelineModal({
flowID: any;
failurePipeline: any;
}) {
- const router = useRouter();
+ const { refreshFlowData } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
@@ -62,7 +62,7 @@ export default function DeleteFailurePipelineModal({
color: "success",
variant: "flat",
});
- router.refresh();
+ refreshFlowData(flowID);
} else {
setIsDeleteLoading(false);
setError(true);
diff --git a/services/frontend/components/modals/failurePipelines/edit.tsx b/services/frontend/components/modals/failurePipelines/edit.tsx
index 8b089469..68672ef9 100644
--- a/services/frontend/components/modals/failurePipelines/edit.tsx
+++ b/services/frontend/components/modals/failurePipelines/edit.tsx
@@ -12,12 +12,12 @@ import {
Select,
SelectItem,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";
import { Icon } from "@iconify/react";
import ErrorCard from "@/components/error/ErrorCard";
import UpdateFlowFailurePipeline from "@/lib/fetch/flow/PUT/UpdateFailurePipeline";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function EditFailurePipelineModal({
disclosure,
@@ -28,7 +28,7 @@ export default function EditFailurePipelineModal({
flow: any;
targetFailurePipeline: any;
}) {
- const router = useRouter();
+ const { refreshFlowData } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [failurePipeline, setFailurePipeline] = useState(targetFailurePipeline);
@@ -94,7 +94,7 @@ export default function EditFailurePipelineModal({
variant: "flat",
});
onOpenChange();
- router.refresh();
+ refreshFlowData(flow.id);
} else {
setError(true);
setErrorText(res.error);
diff --git a/services/frontend/components/projects/project.tsx b/services/frontend/components/projects/project.tsx
index bc490c27..7e1f9f34 100644
--- a/services/frontend/components/projects/project.tsx
+++ b/services/frontend/components/projects/project.tsx
@@ -12,7 +12,6 @@ import {
import NumberFlow from "@number-flow/react";
import React from "react";
-import Reloader from "@/components/reloader/Reloader";
import EditProjectModal from "@/components/modals/projects/edit";
import canEditProject from "@/lib/functions/canEditProject";
@@ -56,9 +55,6 @@ export default function Project({
>
Edit
-
-
-
diff --git a/services/frontend/components/reloader/Reloader.tsx b/services/frontend/components/reloader/Reloader.tsx
deleted file mode 100644
index 90461eda..00000000
--- a/services/frontend/components/reloader/Reloader.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-"use client";
-
-import { CircularProgress, Progress } from "@heroui/react";
-import { useRouter } from "next/navigation";
-import React from "react";
-
-export default function Reloader({
- circle = false,
- refresh = 50,
-}: {
- circle?: boolean;
- refresh?: number;
-}) {
- const [value, setValue] = React.useState(0);
- const router = useRouter();
-
- React.useEffect(() => {
- const interval = setInterval(() => {
- setValue((v) => (v >= 100 ? 0 : v + refresh));
- if (value === 100) {
- clearInterval(interval);
- router.refresh();
- }
- }, 1000);
-
- return () => clearInterval(interval);
- }, [value]);
-
- return circle ? (
-
- ) : (
-
- );
-}
diff --git a/services/frontend/components/runners/heading.tsx b/services/frontend/components/runners/heading.tsx
index 89aacdef..0b7dd649 100644
--- a/services/frontend/components/runners/heading.tsx
+++ b/services/frontend/components/runners/heading.tsx
@@ -1,15 +1,10 @@
"use client";
-import Reloader from "../reloader/Reloader";
-
export default function RunnersHeading() {
return (
);
diff --git a/services/frontend/lib/swr/hooks/flows.ts b/services/frontend/lib/swr/hooks/flows.ts
index 48456a23..45bc11a0 100644
--- a/services/frontend/lib/swr/hooks/flows.ts
+++ b/services/frontend/lib/swr/hooks/flows.ts
@@ -16,6 +16,8 @@ import GetExecutionsWithAttention from "@/lib/fetch/executions/attention";
import GetProjectAuditLogs from "@/lib/fetch/project/audit";
import GetProjectApiKeys from "@/lib/fetch/project/tokens";
import GetExecution from "@/lib/fetch/executions/execution";
+import GetExecutions from "@/lib/fetch/executions/all";
+import GetExecutionSteps from "@/lib/fetch/executions/steps";
// Hook for fetching a single flow
export function useFlow(flowId: string) {
@@ -48,6 +50,49 @@ export function useFlowExecutions(flowId: string) {
};
}
+// Hook for fetching paginated flow executions with filters
+export function useFlowExecutionsPaginated(
+ flowId: string,
+ limit: number = 10,
+ offset: number = 0,
+ status: string | null = null,
+) {
+ const { data, error, mutate, isLoading } = useSWR(
+ flowId
+ ? `flow-executions-paginated-${flowId}-${limit}-${offset}-${status || "all"}`
+ : null,
+ () => GetFlowExecutions(flowId, limit, offset, status),
+ );
+
+ return {
+ executions: data?.success ? data.data.executions : [],
+ total: data?.success ? data.data.total : 0,
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching all executions with pagination and filters
+export function useExecutions(
+ limit: number = 10,
+ offset: number = 0,
+ status: string | null = null,
+) {
+ const { data, error, mutate, isLoading } = useSWR(
+ limit > 0 ? `executions-${limit}-${offset}-${status || "all"}` : null,
+ () => GetExecutions(limit, offset, status),
+ );
+
+ return {
+ executions: data?.success ? data.data.executions : [],
+ total: data?.success ? data.data.total : 0,
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
// Hook for fetching all flows
export function useFlows() {
const { data, error, mutate, isLoading } = useSWR("flows", () => GetFlows());
@@ -248,3 +293,26 @@ export function useExecution(executionId: string) {
refresh: mutate,
};
}
+
+// Hook for fetching execution steps with auto-refresh for running executions
+export function useExecutionSteps(
+ executionId: string,
+ isRunning: boolean = false,
+) {
+ const { data, error, mutate, isLoading } = useSWR(
+ executionId ? `execution-steps-${executionId}` : null,
+ () => GetExecutionSteps(executionId),
+ {
+ refreshInterval: isRunning ? 2000 : 0, // Refresh every 2 seconds if running
+ refreshWhenHidden: false,
+ refreshWhenOffline: false,
+ },
+ );
+
+ return {
+ steps: data?.success ? data.data.steps : [],
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
diff --git a/services/frontend/lib/swr/hooks/useRefreshCache.ts b/services/frontend/lib/swr/hooks/useRefreshCache.ts
index 356995fa..0bb1238f 100644
--- a/services/frontend/lib/swr/hooks/useRefreshCache.ts
+++ b/services/frontend/lib/swr/hooks/useRefreshCache.ts
@@ -24,6 +24,20 @@ export function useRefreshCache() {
refreshFlow: (flowId: string) => mutate(`flow-${flowId}`),
refreshFlowExecutions: (flowId: string) =>
mutate(`flow-executions-${flowId}`),
+ refreshFlowExecutionsPaginated: (
+ flowId: string,
+ limit: number,
+ offset: number,
+ status: string | null = null,
+ ) =>
+ mutate(
+ `flow-executions-paginated-${flowId}-${limit}-${offset}-${status || "all"}`,
+ ),
+ refreshExecutions: (
+ limit: number,
+ offset: number,
+ status: string | null = null,
+ ) => mutate(`executions-${limit}-${offset}-${status || "all"}`),
refreshProject: (projectId: string) => mutate(`project-${projectId}`),
refreshProjectRunners: (projectId: string) =>
mutate(`project-runners-${projectId}`),
@@ -33,10 +47,42 @@ export function useRefreshCache() {
mutate(`project-tokens-${projectId}`),
refreshExecution: (executionId: string) =>
mutate(`execution-${executionId}`),
+ refreshExecutionSteps: (executionId: string) =>
+ mutate(`execution-steps-${executionId}`),
refreshFolder: (folderId: string) => mutate(`folder-${folderId}`),
refreshFolderExecutions: (folderId: string) =>
mutate(`folder-executions-${folderId}`),
+ // Helper to refresh all execution-related caches (useful after deletion)
+ refreshAllExecutionCaches: (flowId?: string) => {
+ // Refresh general execution caches
+ mutate("executions-with-attention");
+ mutate("running-executions");
+
+ // Refresh all paginated execution caches with common pagination values
+ const limits = [4, 6, 10]; // Common limits used in the app
+ const offsets = [0, 10, 20, 30]; // Common offset values
+ const statuses = [null, "all"]; // Common status filters
+
+ limits.forEach((limit) => {
+ offsets.forEach((offset) => {
+ statuses.forEach((status) => {
+ mutate(`executions-${limit}-${offset}-${status || "all"}`);
+ if (flowId) {
+ mutate(
+ `flow-executions-paginated-${flowId}-${limit}-${offset}-${status || "all"}`,
+ );
+ }
+ });
+ });
+ });
+
+ // Refresh specific flow executions if flowId provided
+ if (flowId) {
+ mutate(`flow-executions-${flowId}`);
+ }
+ },
+
// Convenience methods for common combinations
refreshAll: () => {
mutate("flows");
diff --git a/services/frontend/lib/swr/provider.tsx b/services/frontend/lib/swr/provider.tsx
index 8d710cbc..e338ec5b 100644
--- a/services/frontend/lib/swr/provider.tsx
+++ b/services/frontend/lib/swr/provider.tsx
@@ -13,7 +13,7 @@ export default function SWRProvider({ children }: SWRProviderProps) {
value={{
revalidateOnFocus: true,
revalidateOnReconnect: true,
- refreshInterval: 30000, // Refresh every 30 seconds
+ refreshInterval: 10000, // Refresh every 10 seconds
errorRetryCount: 3,
errorRetryInterval: 5000,
dedupingInterval: 2000,
From cb0995fba2d63b3502aaafe0ce445e63696cf1d5 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Tue, 19 Aug 2025 16:28:05 +0200
Subject: [PATCH 13/45] refactor: replace useRouter with useRefreshCache for
improved cache management in project modals
---
.../components/modals/projects/changeTokenStatus.tsx | 8 ++++----
.../components/modals/projects/createToken.tsx | 12 +++++++++---
.../components/modals/projects/deleteToken.tsx | 6 +++---
.../components/modals/projects/editMember.tsx | 6 +++---
.../frontend/components/modals/projects/leave.tsx | 6 +++---
.../frontend/components/modals/projects/members.tsx | 6 +++---
.../components/modals/projects/removeMember.tsx | 6 +++---
.../modals/projects/rotateAutoJoinToken.tsx | 6 +++---
.../components/modals/projects/transferOwnership.tsx | 6 +++---
.../components/modals/runner/changeStatus.tsx | 8 ++++----
.../frontend/components/modals/runner/create.tsx | 6 +++---
.../frontend/components/modals/runner/delete.tsx | 8 ++++----
services/frontend/components/modals/runner/edit.tsx | 6 +++---
.../components/modals/tokens/deleteRunnerToken.tsx | 6 +++---
services/frontend/components/modals/tokens/edit.tsx | 6 +++---
services/frontend/components/modals/user/welcome.tsx | 4 +---
16 files changed, 55 insertions(+), 51 deletions(-)
diff --git a/services/frontend/components/modals/projects/changeTokenStatus.tsx b/services/frontend/components/modals/projects/changeTokenStatus.tsx
index bfeb3c2d..59bbc609 100644
--- a/services/frontend/components/modals/projects/changeTokenStatus.tsx
+++ b/services/frontend/components/modals/projects/changeTokenStatus.tsx
@@ -11,12 +11,12 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import { Icon } from "@iconify/react";
import ErrorCard from "@/components/error/ErrorCard";
import ChangeProjectTokenStatus from "@/lib/fetch/project/PUT/ChangeProjectTokenStatus";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function ChangeProjectTokenStatusModal({
disclosure,
@@ -29,7 +29,7 @@ export default function ChangeProjectTokenStatusModal({
token: any;
disabled: any;
}) {
- const router = useRouter();
+ const { refreshProjectTokens } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
@@ -70,7 +70,7 @@ export default function ChangeProjectTokenStatusModal({
setErrorText("");
setErrorMessage("");
onOpenChange();
- router.refresh();
+ refreshProjectTokens(projectID);
addToast({
title: "Project",
description: "Token status updated successfully",
@@ -82,7 +82,7 @@ export default function ChangeProjectTokenStatusModal({
setError(true);
setErrorText(res.error);
setErrorMessage(res.message);
- router.refresh();
+ refreshProjectTokens(projectID);
addToast({
title: "Project",
description: "Failed to update token status",
diff --git a/services/frontend/components/modals/projects/createToken.tsx b/services/frontend/components/modals/projects/createToken.tsx
index b94fc4e8..b0b66b5c 100644
--- a/services/frontend/components/modals/projects/createToken.tsx
+++ b/services/frontend/components/modals/projects/createToken.tsx
@@ -12,12 +12,12 @@ import {
ModalContent,
ModalHeader,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useState } from "react";
import { Icon } from "@iconify/react";
import ErrorCard from "@/components/error/ErrorCard";
import CreateProjectToken from "@/lib/fetch/project/POST/CreateProjectToken";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function CreateProjectTokenModal({
disclosure,
@@ -26,7 +26,7 @@ export default function CreateProjectTokenModal({
disclosure: UseDisclosureReturn;
projectID: any;
}) {
- const router = useRouter();
+ const { refreshProjectTokens } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [errors] = useState({});
@@ -65,8 +65,14 @@ export default function CreateProjectTokenModal({
}
if (res.success) {
- router.refresh();
+ refreshProjectTokens(projectID);
onOpenChange();
+ addToast({
+ title: "Project",
+ description: "Token created successfully",
+ color: "success",
+ variant: "flat",
+ });
} else {
setApiError(true);
setApiErrorText(res.error);
diff --git a/services/frontend/components/modals/projects/deleteToken.tsx b/services/frontend/components/modals/projects/deleteToken.tsx
index b1dc3c8d..016df7bf 100644
--- a/services/frontend/components/modals/projects/deleteToken.tsx
+++ b/services/frontend/components/modals/projects/deleteToken.tsx
@@ -12,12 +12,12 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import { Icon } from "@iconify/react";
import ErrorCard from "@/components/error/ErrorCard";
import DeleteProjectToken from "@/lib/fetch/project/DELETE/DeleteProjectToken";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function DeleteProjectTokenModal({
disclosure,
@@ -28,7 +28,7 @@ export default function DeleteProjectTokenModal({
projectID: any;
token: any;
}) {
- const router = useRouter();
+ const { refreshProjectTokens } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [isLoading, setIsLoading] = React.useState(false);
@@ -61,7 +61,7 @@ export default function DeleteProjectTokenModal({
setError(false);
setErrorText("");
setErrorMessage("");
- router.refresh();
+ refreshProjectTokens(projectID);
onOpenChange();
addToast({
title: "Token",
diff --git a/services/frontend/components/modals/projects/editMember.tsx b/services/frontend/components/modals/projects/editMember.tsx
index 15cd9c4e..77a85f01 100644
--- a/services/frontend/components/modals/projects/editMember.tsx
+++ b/services/frontend/components/modals/projects/editMember.tsx
@@ -13,12 +13,12 @@ import {
Select,
SelectItem,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";
import { Icon } from "@iconify/react";
import EditProjectMember from "@/lib/fetch/project/PUT/editProjectMember";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function EditProjectMemberModal({
disclosure,
@@ -29,7 +29,7 @@ export default function EditProjectMemberModal({
projectID: string;
user: any;
}) {
- const router = useRouter();
+ const { refreshProject } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [isLoginLoading, setIsLoginLoading] = useState(false);
const [role, setRole] = React.useState(user.role);
@@ -82,7 +82,7 @@ export default function EditProjectMemberModal({
color: "success",
variant: "flat",
});
- router.refresh();
+ refreshProject(projectID);
} else {
setError(true);
setErrorText(response.error);
diff --git a/services/frontend/components/modals/projects/leave.tsx b/services/frontend/components/modals/projects/leave.tsx
index daf2f555..13a18130 100644
--- a/services/frontend/components/modals/projects/leave.tsx
+++ b/services/frontend/components/modals/projects/leave.tsx
@@ -11,12 +11,12 @@ import {
ModalFooter,
ModalHeader,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useState } from "react";
import { Icon } from "@iconify/react";
import LeaveProject from "@/lib/fetch/project/DELETE/leave";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function LeaveProjectModal({
disclosure,
@@ -25,7 +25,7 @@ export default function LeaveProjectModal({
disclosure: UseDisclosureReturn;
projectID: string;
}) {
- const router = useRouter();
+ const { refreshProject } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [isLeaveLoading, setIsLeaveLoading] = useState(false);
@@ -65,7 +65,7 @@ export default function LeaveProjectModal({
color: "success",
variant: "flat",
});
- router.push("/projects");
+ refreshProject(projectID);
} else {
setIsLeaveLoading(false);
setError(true);
diff --git a/services/frontend/components/modals/projects/members.tsx b/services/frontend/components/modals/projects/members.tsx
index 609e1cff..738013e1 100644
--- a/services/frontend/components/modals/projects/members.tsx
+++ b/services/frontend/components/modals/projects/members.tsx
@@ -24,11 +24,11 @@ import {
ModalContent,
Spacer,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import AddProjectMember from "@/lib/fetch/project/POST/AddProjectMember";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
import UserCell from "./user-cell";
@@ -39,7 +39,7 @@ export default function AddProjectMemberModal({
disclosure: UseDisclosureReturn;
project: any;
}) {
- const router = useRouter();
+ const { refreshProject } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [email, setEmail] = React.useState("");
@@ -120,7 +120,7 @@ export default function AddProjectMemberModal({
setErrorText("");
setErrorMessage("");
onOpenChange();
- router.refresh();
+ refreshProject(project.id);
addToast({
title: "Project",
description: "Member invited successfully",
diff --git a/services/frontend/components/modals/projects/removeMember.tsx b/services/frontend/components/modals/projects/removeMember.tsx
index 6de9a6d0..9d096b1f 100644
--- a/services/frontend/components/modals/projects/removeMember.tsx
+++ b/services/frontend/components/modals/projects/removeMember.tsx
@@ -13,12 +13,12 @@ import {
ModalHeader,
User,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useState } from "react";
import { Icon } from "@iconify/react";
import RemoveProjectMember from "@/lib/fetch/project/DELETE/removeProjectMember";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function DeleteProjectMemberModal({
disclosure,
@@ -29,7 +29,7 @@ export default function DeleteProjectMemberModal({
projectID: string;
user: any;
}) {
- const router = useRouter();
+ const { refreshProject } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
@@ -75,7 +75,7 @@ export default function DeleteProjectMemberModal({
color: "success",
variant: "flat",
});
- router.refresh();
+ refreshProject(projectID);
} else {
setError(true);
setErrorText(res.error);
diff --git a/services/frontend/components/modals/projects/rotateAutoJoinToken.tsx b/services/frontend/components/modals/projects/rotateAutoJoinToken.tsx
index 4dcd3eec..1d270827 100644
--- a/services/frontend/components/modals/projects/rotateAutoJoinToken.tsx
+++ b/services/frontend/components/modals/projects/rotateAutoJoinToken.tsx
@@ -11,12 +11,12 @@ import {
ModalFooter,
ModalHeader,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import { Icon } from "@iconify/react";
import ErrorCard from "@/components/error/ErrorCard";
import RotateAutoJoinToken from "@/lib/fetch/project/PUT/RotateAutoJoinToken";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function RotateAutoJoinTokenModal({
disclosure,
@@ -25,7 +25,7 @@ export default function RotateAutoJoinTokenModal({
disclosure: UseDisclosureReturn;
projectID: any;
}) {
- const router = useRouter();
+ const { refreshProject } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [isLoading, setIsLoading] = React.useState(false);
@@ -58,7 +58,7 @@ export default function RotateAutoJoinTokenModal({
setError(false);
setErrorText("");
setErrorMessage("");
- router.refresh();
+ refreshProject(projectID);
onOpenChange();
addToast({
title: "Token",
diff --git a/services/frontend/components/modals/projects/transferOwnership.tsx b/services/frontend/components/modals/projects/transferOwnership.tsx
index b0398d00..c3e58fbd 100644
--- a/services/frontend/components/modals/projects/transferOwnership.tsx
+++ b/services/frontend/components/modals/projects/transferOwnership.tsx
@@ -21,12 +21,12 @@ import {
Spacer,
User,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useState } from "react";
import { Icon } from "@iconify/react";
import ProjectTransferOwnershipAPI from "@/lib/fetch/project/PUT/transferOwnership";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function ProjectTransferOwnership({
disclosure,
@@ -37,7 +37,7 @@ export default function ProjectTransferOwnership({
project: any;
user: any;
}) {
- const router = useRouter();
+ const { refreshProject } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [isLoading, setIsLoading] = useState(false);
@@ -88,7 +88,7 @@ export default function ProjectTransferOwnership({
setError(false);
setErrorText("");
setErrorMessage("");
- router.refresh();
+ refreshProject(project.id);
addToast({
title: "Project",
description: "Owner transferred successfully",
diff --git a/services/frontend/components/modals/runner/changeStatus.tsx b/services/frontend/components/modals/runner/changeStatus.tsx
index 5cdb3de8..73498e0f 100644
--- a/services/frontend/components/modals/runner/changeStatus.tsx
+++ b/services/frontend/components/modals/runner/changeStatus.tsx
@@ -11,12 +11,12 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import { Icon } from "@iconify/react";
import ErrorCard from "@/components/error/ErrorCard";
import ChangeRunnerStatus from "@/lib/fetch/admin/PUT/ChangeRunnerStatus";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function ChangeRunnerStatusModal({
disclosure,
@@ -27,7 +27,7 @@ export default function ChangeRunnerStatusModal({
runner: any;
status: any;
}) {
- const router = useRouter();
+ const { refreshRunners } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
@@ -67,7 +67,7 @@ export default function ChangeRunnerStatusModal({
setErrorText("");
setErrorMessage("");
onOpenChange();
- router.refresh();
+ refreshRunners();
addToast({
title: "Runner",
description: "Runner status updated successfully",
@@ -79,7 +79,7 @@ export default function ChangeRunnerStatusModal({
setError(true);
setErrorText(res.error);
setErrorMessage(res.message);
- router.refresh();
+ refreshRunners();
addToast({
title: "Runner",
description: "Failed to update runner status",
diff --git a/services/frontend/components/modals/runner/create.tsx b/services/frontend/components/modals/runner/create.tsx
index 624a1d38..d114b57b 100644
--- a/services/frontend/components/modals/runner/create.tsx
+++ b/services/frontend/components/modals/runner/create.tsx
@@ -15,12 +15,12 @@ import {
Snippet,
useDisclosure,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useState } from "react";
import { Icon } from "@iconify/react";
import AddRunner from "@/lib/fetch/runner/POST/AddRunner";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function CreateRunnerModal({
disclosure,
@@ -31,7 +31,7 @@ export default function CreateRunnerModal({
project: any;
shared_runner: any;
}) {
- const router = useRouter();
+ const { refreshProjectRunners } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
// instructions modal
@@ -85,7 +85,7 @@ export default function CreateRunnerModal({
setInApikey(res.data.token);
setInRunnerId(res.data.runner.id);
onOpenChangeInstructions();
- router.refresh();
+ refreshProjectRunners(project.id);
addToast({
title: "Runner",
description: "Runner created successfully",
diff --git a/services/frontend/components/modals/runner/delete.tsx b/services/frontend/components/modals/runner/delete.tsx
index 69ec9dfe..8e85f44f 100644
--- a/services/frontend/components/modals/runner/delete.tsx
+++ b/services/frontend/components/modals/runner/delete.tsx
@@ -14,13 +14,13 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useEffect } from "react";
import { Icon } from "@iconify/react";
import GetRunnerFlowLinks from "@/lib/fetch/runner/GetRunnerFlowLinks";
import DeleteProjectRunner from "@/lib/fetch/project/DELETE/DeleteRunner";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function DeleteRunnerModal({
disclosure,
@@ -29,7 +29,7 @@ export default function DeleteRunnerModal({
disclosure: UseDisclosureReturn;
runner: any;
}) {
- const router = useRouter();
+ const { refreshRunners } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [flowLinks, setFlowLinks] = React.useState([]);
@@ -49,7 +49,7 @@ export default function DeleteRunnerModal({
setError(true);
setErrorText("Failed to fetch runner flow links");
setErrorMessage("An error occurred while fetching the runner flow links");
- router.refresh();
+ refreshRunners();
addToast({
title: "Runner",
description: "Failed to fetch runner flow links",
@@ -101,7 +101,7 @@ export default function DeleteRunnerModal({
color: "success",
variant: "flat",
});
- router.refresh();
+ refreshRunners();
} else {
setError(true);
setErrorText(response.error);
diff --git a/services/frontend/components/modals/runner/edit.tsx b/services/frontend/components/modals/runner/edit.tsx
index d9512ece..2bafd5bb 100644
--- a/services/frontend/components/modals/runner/edit.tsx
+++ b/services/frontend/components/modals/runner/edit.tsx
@@ -12,12 +12,12 @@ import {
ModalContent,
ModalHeader,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useState } from "react";
import { Icon } from "@iconify/react";
import EditRunner from "@/lib/fetch/runner/PUT/Edit";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function EditRunnerModal({
disclosure,
@@ -26,7 +26,7 @@ export default function EditRunnerModal({
disclosure: UseDisclosureReturn;
runner: any;
}) {
- const router = useRouter();
+ const { refreshRunners } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [isLoading, setIsLoading] = useState(false);
@@ -71,7 +71,7 @@ export default function EditRunnerModal({
color: "success",
variant: "flat",
});
- router.refresh();
+ refreshRunners();
} else {
setApiError(true);
setApiErrorText(res.error);
diff --git a/services/frontend/components/modals/tokens/deleteRunnerToken.tsx b/services/frontend/components/modals/tokens/deleteRunnerToken.tsx
index 1b6f0505..624fc277 100644
--- a/services/frontend/components/modals/tokens/deleteRunnerToken.tsx
+++ b/services/frontend/components/modals/tokens/deleteRunnerToken.tsx
@@ -12,11 +12,11 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import DeleteRunnerToken from "@/lib/fetch/project/DELETE/DeleteRunnerToken";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function DeleteRunnerTokenModal({
disclosure,
@@ -25,7 +25,7 @@ export default function DeleteRunnerTokenModal({
disclosure: UseDisclosureReturn;
token: any;
}) {
- const router = useRouter();
+ const { refreshProjectTokens } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [isLoading, setIsLoading] = React.useState(false);
@@ -58,7 +58,7 @@ export default function DeleteRunnerTokenModal({
setError(false);
setErrorText("");
setErrorMessage("");
- router.refresh();
+ refreshProjectTokens(token.project_id);
onOpenChange();
addToast({
title: "Token",
diff --git a/services/frontend/components/modals/tokens/edit.tsx b/services/frontend/components/modals/tokens/edit.tsx
index f8618976..20dd27e8 100644
--- a/services/frontend/components/modals/tokens/edit.tsx
+++ b/services/frontend/components/modals/tokens/edit.tsx
@@ -12,12 +12,12 @@ import {
ModalContent,
ModalHeader,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React, { useState } from "react";
import { Icon } from "@iconify/react";
import UpdateToken from "@/lib/fetch/tokens/update";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function EditTokenModal({
token,
@@ -26,7 +26,7 @@ export default function EditTokenModal({
token: any;
disclosure: UseDisclosureReturn;
}) {
- const router = useRouter();
+ const { refreshProjectTokens } = useRefreshCache();
// create modal
const { isOpen, onOpenChange, onClose } = disclosure;
@@ -69,7 +69,7 @@ export default function EditTokenModal({
setApiError(false);
setApiErrorText("");
setApiErrorMessage("");
- router.refresh();
+ refreshProjectTokens(token.project_id);
onOpenChange();
} else {
setIsLoading(false);
diff --git a/services/frontend/components/modals/user/welcome.tsx b/services/frontend/components/modals/user/welcome.tsx
index d5d028fb..6a7f02ea 100644
--- a/services/frontend/components/modals/user/welcome.tsx
+++ b/services/frontend/components/modals/user/welcome.tsx
@@ -12,7 +12,6 @@ import {
ModalFooter,
ModalHeader,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import ErrorCard from "@/components/error/ErrorCard";
@@ -23,7 +22,6 @@ export default function WelcomeModal({
}: {
disclosure: UseDisclosureReturn;
}) {
- const router = useRouter();
const { isOpen, onOpenChange } = disclosure;
const [error, setError] = React.useState(false);
@@ -76,7 +74,7 @@ export default function WelcomeModal({
onOpenChange={onOpenChange}
>
- {(onClose) => (
+ {() => (
<>
From dcd02a482944688802532f72d97969b740c06138 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Tue, 19 Aug 2025 16:33:59 +0200
Subject: [PATCH 14/45] refactor: remove unused Reloader component from
AdminRunnersHeading and AdminSettingsHeading
---
services/frontend/components/admin/runners/heading.tsx | 3 ---
services/frontend/components/admin/settings/heading.tsx | 5 -----
2 files changed, 8 deletions(-)
diff --git a/services/frontend/components/admin/runners/heading.tsx b/services/frontend/components/admin/runners/heading.tsx
index 21e53ba8..e1de23e0 100644
--- a/services/frontend/components/admin/runners/heading.tsx
+++ b/services/frontend/components/admin/runners/heading.tsx
@@ -4,7 +4,6 @@ import { addToast, Button, useDisclosure } from "@heroui/react";
import { Icon } from "@iconify/react";
import CreateProjectModal from "@/components/modals/projects/create";
-import Reloader from "@/components/reloader/Reloader";
import RotateSharedAutoJoinTokenModal from "@/components/modals/admin/rotateSharedAutoJoinToken";
export default function AdminRunnersHeading({ settings }: any) {
@@ -61,8 +60,6 @@ export default function AdminRunnersHeading({ settings }: any) {
-
-
diff --git a/services/frontend/components/admin/settings/heading.tsx b/services/frontend/components/admin/settings/heading.tsx
index 600c1369..f8506bfb 100644
--- a/services/frontend/components/admin/settings/heading.tsx
+++ b/services/frontend/components/admin/settings/heading.tsx
@@ -1,7 +1,5 @@
"use client";
-import Reloader from "@/components/reloader/Reloader";
-
export default function AdminSettingsHeading() {
return (
@@ -11,9 +9,6 @@ export default function AdminSettingsHeading() {
Admin | exFlow Settings
-
-
-
);
From 4b8f673d57435248d746bfa4517d0c109d3e24d9 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Tue, 19 Aug 2025 11:46:25 +0200
Subject: [PATCH 15/45] feat: add Flow Failure Pipelines component with
drag-and-drop functionality for actions
- Implemented FlowFailurePipelines component to manage failure pipelines.
- Integrated drag-and-drop sorting for actions within failure pipelines.
- Added modals for creating, editing, deleting, and managing actions in failure pipelines.
- Updated FlowTabs to include a new tab for Failure Pipelines.
- Adjusted FlowHeading to improve button accessibility and layout.
- Modified ProjectsList to enhance project card layout and added footer with creation date.
- Updated EditFailurePipelineModal size for better user experience.
---
.../execution/adminExecutionActions.tsx | 2 +-
.../executions/execution/execution.tsx | 6 +-
.../components/flows/flow/actions.tsx | 852 +++------------
.../flows/flow/failure-pipelines.tsx | 983 ++++++++++++++++++
.../components/flows/flow/heading.tsx | 2 +-
.../frontend/components/flows/flow/tabs.tsx | 23 +-
.../modals/failurePipelines/edit.tsx | 2 +-
.../frontend/components/projects/list.tsx | 146 +--
8 files changed, 1223 insertions(+), 793 deletions(-)
create mode 100644 services/frontend/components/flows/flow/failure-pipelines.tsx
diff --git a/services/frontend/components/executions/execution/adminExecutionActions.tsx b/services/frontend/components/executions/execution/adminExecutionActions.tsx
index fe406aeb..bc308b77 100644
--- a/services/frontend/components/executions/execution/adminExecutionActions.tsx
+++ b/services/frontend/components/executions/execution/adminExecutionActions.tsx
@@ -121,7 +121,7 @@ export default function AdminExecutionActions({
-
+
Admin Actions
diff --git a/services/frontend/components/executions/execution/execution.tsx b/services/frontend/components/executions/execution/execution.tsx
index 0263d446..5dfd84f5 100644
--- a/services/frontend/components/executions/execution/execution.tsx
+++ b/services/frontend/components/executions/execution/execution.tsx
@@ -56,11 +56,7 @@ export function Execution({ flow, execution, runners, userDetails }: any) {
return (
<>
- router.back()}
- >
+ router.back()}>
Back
diff --git a/services/frontend/components/flows/flow/actions.tsx b/services/frontend/components/flows/flow/actions.tsx
index ec136c62..c473b28d 100644
--- a/services/frontend/components/flows/flow/actions.tsx
+++ b/services/frontend/components/flows/flow/actions.tsx
@@ -8,8 +8,6 @@ import {
import { CSS } from "@dnd-kit/utilities";
import { Icon } from "@iconify/react";
import {
- Accordion,
- AccordionItem,
addToast,
Alert,
Button,
@@ -23,7 +21,6 @@ import {
DropdownItem,
DropdownMenu,
DropdownTrigger,
- ScrollShadow,
Snippet,
Spacer,
Switch,
@@ -39,17 +36,12 @@ import {
useDisclosure,
} from "@heroui/react";
import React, { useEffect } from "react";
-import { useRouter } from "next/navigation";
import UpdateFlowActions from "@/lib/fetch/flow/PUT/UpdateActions";
import EditFlowActionsDetails from "@/components/modals/actions/editDetails";
import EditActionModal from "@/components/modals/actions/edit";
import DeleteActionModal from "@/components/modals/actions/delete";
import AddActionModal from "@/components/modals/actions/add";
-import CreateFailurePipelineModal from "@/components/modals/failurePipelines/create";
-import DeleteFailurePipelineModal from "@/components/modals/failurePipelines/delete";
-import EditFailurePipelineModal from "@/components/modals/failurePipelines/edit";
-import UpdateFlowFailurePipelineActions from "@/lib/fetch/flow/PUT/UpdateFailurePipelineActions";
import CopyActionModal from "@/components/modals/actions/copy";
import UpgradeActionModal from "@/components/modals/actions/upgrade";
import CopyActionToDifferentFlowModal from "@/components/modals/actions/transferCopy";
@@ -71,56 +63,23 @@ export default function Actions({
canEdit: boolean;
settings: any;
}) {
- const router = useRouter();
-
const [actions, setActions] = React.useState([] as any);
const [targetAction, setTargetAction] = React.useState({} as any);
const [updatedAction, setUpdatedAction] = React.useState({} as any);
const [showDefaultParams, setShowDefaultParams] = React.useState(false);
- const [failurePipelines, setFailurePipelines] = React.useState([] as any);
- const [targetFailurePipeline, setTargetFailurePipeline] = React.useState(
- {} as any,
- );
-
- const [failurePipelineTab, setFailurePipelineTab] =
- React.useState("add-pipeline");
-
const editFlowActionsDetails = useDisclosure();
const addFlowActionModal = useDisclosure();
const editActionModal = useDisclosure();
const copyFlowActionModal = useDisclosure();
const upgradeFlowActionModal = useDisclosure();
const deleteActionModal = useDisclosure();
- const createFlowFailurePipelineModal = useDisclosure();
- const editFlowFailurePipelineModal = useDisclosure();
- const deleteFailurePipelineModal = useDisclosure();
- const addFlowFailurePipelineActionModal = useDisclosure();
- const editFlowFailurePipelineActionModal = useDisclosure();
- const deleteFlowFailurePipelineActionModal = useDisclosure();
- const copyFlowFailurePipelineActionModal = useDisclosure();
- const upgradeFlowFailurePipelineActionModal = useDisclosure();
const copyActionToDifferentFlowModal = useDisclosure();
- const copyFailurePipelineActionToDifferentFlowModal = useDisclosure();
-
- const [expandedParams, setExpandedParams] = React.useState([] as any);
useEffect(() => {
setActions(flow.actions);
-
- if (flow.failure_pipelines !== null) {
- setFailurePipelines(flow.failure_pipelines);
-
- if (failurePipelineTab === "add-pipeline") {
- setFailurePipelineTab(flow.failure_pipelines[0]?.id || "add-pipeline");
- }
- }
- }, [flow]);
-
- const handleFailurePipelineTabChange = (key: any) => {
- setFailurePipelineTab(key);
- };
+ }, [flow.actions]);
// function to get action from clipboard
const getClipboardAction = async () => {
@@ -213,46 +172,7 @@ export default function Actions({
-
- {
- // if action is in an failure pipeline, open the edit modal
- if (
- flow.failure_pipelines.some(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )
- ) {
- setTargetAction(action);
- setTargetFailurePipeline(
- flow.failure_pipelines.filter(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )[0],
- );
- editFlowFailurePipelineActionModal.onOpen();
- } else {
- setTargetAction(action);
- editActionModal.onOpen();
- }
- }}
- >
-
-
+
-
+
+
}
onPress={() => {
navigator.clipboard.writeText(
@@ -284,91 +205,55 @@ export default function Actions({
});
}}
>
- Copy to Clipboard
+ Clipboard
}
onPress={() => {
- // if action is in an failure pipeline, open the edit modal
- if (
- flow.failure_pipelines.some(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )
- ) {
- setTargetAction(action);
- setTargetFailurePipeline(
- flow.failure_pipelines.filter(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )[0],
- );
- copyFlowFailurePipelineActionModal.onOpen();
- } else {
- setTargetAction(action);
- copyFlowActionModal.onOpen();
- }
+ setTargetAction(action);
+ copyFlowActionModal.onOpen();
}}
>
- Copy Locally
+ Local
}
onPress={() => {
- // if action is in an failure pipeline, open the edit modal
- if (
- flow.failure_pipelines.some(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )
- ) {
- setTargetAction(action);
- setTargetFailurePipeline(
- flow.failure_pipelines.filter(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )[0],
- );
- copyFailurePipelineActionToDifferentFlowModal.onOpen();
- } else {
- setTargetAction(action);
- copyActionToDifferentFlowModal.onOpen();
- }
+ setTargetAction(action);
+ copyActionToDifferentFlowModal.onOpen();
}}
>
- Copy to another Flow
+ Transfer
+ {
+ setTargetAction(action);
+ editActionModal.onOpen();
+ }}
+ >
+
+
{
- // if action is in an failure pipeline, open the edit modal
- if (
- flow.failure_pipelines.some(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )
- ) {
- setTargetAction(action.id);
- setTargetFailurePipeline(
- flow.failure_pipelines.filter(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )[0],
- );
- deleteFlowFailurePipelineActionModal.onOpen();
- } else {
- setTargetAction(action.id);
- deleteActionModal.onOpen();
- }
+ setTargetAction(action.id);
+ deleteActionModal.onOpen();
}}
>
-
+
@@ -415,11 +275,12 @@ export default function Actions({
isDisabled={
(!canEdit || flow.disabled) && user.role !== "admin"
}
+ size="sm"
variant="flat"
{...listeners}
style={{ cursor: "grab", touchAction: "none" }}
>
-
+
@@ -466,74 +327,43 @@ export default function Actions({
))}
- {action.update_available && (
-
+ {action.update_available && (
+
+
+ description="Newer plugin version was found on one of the runners. Do you want to upgrade the action plugin version?"
+ endContent={
+
+ }
+ variant="flat"
+ onPress={() => {
+ setTargetAction(action);
+ setUpdatedAction(action.updated_action);
+ upgradeFlowActionModal.onOpen();
+ }}
+ >
+ Upgrade
+
}
- variant="flat"
- onPress={() => {
- // if action is in an failure pipeline, open the edit modal
- if (
- flow.failure_pipelines.some(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )
- ) {
- setTargetAction(action);
- setUpdatedAction(action.updated_action);
- setTargetFailurePipeline(
- flow.failure_pipelines.filter(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )[0],
- );
- upgradeFlowFailurePipelineActionModal.onOpen();
- } else {
- setTargetAction(action);
- setUpdatedAction(action.updated_action);
- upgradeFlowActionModal.onOpen();
- }
- }}
- >
- Upgrade
-
- }
- title={`Update to version ${action.update_version} available`}
- variant="faded"
- />
- )}
-
-
+ title={`Update to version ${action.update_version} available`}
+ variant="faded"
+ />
+
+ )}
+
-
+
{action.params.length > 0 && (
-
+
-
+
)}
{action.condition.selected_action_id !== "" && (
-
+
@@ -780,409 +600,82 @@ export default function Actions({
});
}
- const handleDragEndPipeline = (pipeline: any, event: any) => {
- const { active, over } = event;
-
- if (active.id !== over.id) {
- const items = [...pipeline.actions];
- const oldIndex = items.findIndex((item: any) => item.id === active.id);
- const newIndex = items.findIndex((item: any) => item.id === over.id);
-
- const newArray = arrayMove(items, oldIndex, newIndex);
-
- updateFlowFailurePipelineActions(pipeline, newArray);
- }
- };
-
- function updateFlowFailurePipelineActions(pipeline: any, actions: any) {
- UpdateFlowFailurePipelineActions(flow.id, pipeline.id, actions)
- .then(() => {
- router.refresh();
- addToast({
- title: "Flow",
- description:
- "Flow failure pipeline actions order updated successfully.",
- color: "success",
- variant: "flat",
- });
- })
- .catch(() => {
- router.refresh();
- addToast({
- title: "Flow",
- description: "Failed to update flow failure pipeline actions order.",
- color: "danger",
- variant: "flat",
- });
- });
- }
-
return (
-
- Info: Common action settings can be found on the settings tab
-
-
-
-
-
-
-
-
- {actions.map((action: any) => (
-
- ))}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Create new Action
-
- Add a new action to the flow
-
-
-
-
-
-
-
-
{
- const parsedAction = await getClipboardAction();
-
- if (parsedAction) {
- setTargetAction(parsedAction);
- copyFlowActionModal.onOpen();
- } else {
- addToast({
- title: "Flow",
- description: "No action found in clipboard.",
- color: "danger",
- variant: "flat",
- });
- }
- }}
- >
-
-
-
-
-
-
-
-
- Paste Action from Clipboard
-
-
- You have an action copied to the clipboard.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Failure Pipelines
-
- With failure pipelines you have the ability to send
- notifications or trigger any other action if a specific action
- or the whole execution failed.
+
+
+
+
+
Actions
+
+ Common action settings can be found on the settings tab
-
-
- {failurePipelines.map((pipeline: any) => (
-
-
-
-
-
-
-
-
{pipeline.name}
-
-
- {pipeline.exec_parallel
- ? "Parallel"
- : "Sequential"}
-
-
- action.failure_pipeline_id ===
- pipeline.id,
- ).length > 0
- ? "success"
- : "danger"
- }
- radius="sm"
- size="sm"
- variant="flat"
- >
- {flow.failure_pipeline_id === pipeline.id
- ? "Assigned to Flow"
- : flow.actions.filter(
- (action: any) =>
- action.failure_pipeline_id ===
- pipeline.id,
- ).length > 0
- ? "Assigned on Action"
- : "Not Assigned"}
-
-
-
-
- {pipeline.id}
-
-
-
-
- }
- variant="light"
- onPress={() => {
- setTargetFailurePipeline(pipeline);
- editFlowFailurePipelineModal.onOpen();
- }}
- >
- Edit Pipeline
-
-
- }
- variant="light"
- onPress={() => {
- setTargetFailurePipeline(pipeline.id);
- deleteFailurePipelineModal.onOpen();
- }}
- >
- Delete Pipeline
-
-
-
-
-
-
-
- handleDragEndPipeline(pipeline, event)
- }
- >
-
-
- {pipeline.actions !== null &&
- pipeline.actions.length > 0 &&
- pipeline.actions.map((action: any) => (
-
- ))}
-
-
-
-
-
-
-
{
- setTargetFailurePipeline(pipeline);
- addFlowFailurePipelineActionModal.onOpen();
- }}
- >
-
-
-
-
-
-
-
-
- Create new Action
-
-
- Add a new action to the failure pipeline
-
-
-
-
-
-
-
-
{
- const parsedAction = await getClipboardAction();
-
- if (parsedAction) {
- setTargetAction(parsedAction);
- setTargetFailurePipeline(pipeline);
- copyFlowFailurePipelineActionModal.onOpen();
- } else {
- addToast({
- title: "Flow",
- description: "No action found in clipboard.",
- color: "danger",
- variant: "flat",
- });
- }
- }}
- >
-
-
-
-
-
-
-
-
- Paste Action from Clipboard
-
-
- You have an action copied to the clipboard.
-
-
-
-
-
-
-
-
-
- ))}
-
+
+ }
+ variant="solid"
+ onPress={addFlowActionModal.onOpen}
+ />
+
+
+ }
variant="light"
- onPress={() => {
- createFlowFailurePipelineModal.onOpen();
+ onPress={async () => {
+ const parsedAction = await getClipboardAction();
+
+ if (parsedAction) {
+ setTargetAction(parsedAction);
+ copyFlowActionModal.onOpen();
+ } else {
+ addToast({
+ title: "Flow",
+ description: "No action found in clipboard.",
+ color: "danger",
+ variant: "flat",
+ });
+ }
}}
- >
-
-
- }
- />
-
- {flow.failure_pipelines !== null &&
- flow.failure_pipelines.length === 0 && (
-
-
- No failure pipelines defined.
-
-
- )}
-
+ />
+
+
+
+
+
+
+
+
+
+
+ {actions.map((action: any) => (
+
+ ))}
+
+
+
-
-
-
-
-
-
-
-
-
-
-
);
}
diff --git a/services/frontend/components/flows/flow/failure-pipelines.tsx b/services/frontend/components/flows/flow/failure-pipelines.tsx
new file mode 100644
index 00000000..ca53ffac
--- /dev/null
+++ b/services/frontend/components/flows/flow/failure-pipelines.tsx
@@ -0,0 +1,983 @@
+import { closestCenter, DndContext } from "@dnd-kit/core";
+import {
+ arrayMove,
+ SortableContext,
+ useSortable,
+ verticalListSortingStrategy,
+} from "@dnd-kit/sortable";
+import { CSS } from "@dnd-kit/utilities";
+import { Icon } from "@iconify/react";
+import {
+ Accordion,
+ AccordionItem,
+ addToast,
+ Alert,
+ Button,
+ ButtonGroup,
+ Card,
+ CardBody,
+ Checkbox,
+ Chip,
+ Divider,
+ Dropdown,
+ DropdownItem,
+ DropdownMenu,
+ DropdownTrigger,
+ ScrollShadow,
+ Snippet,
+ Spacer,
+ Switch,
+ Tab,
+ Table,
+ TableBody,
+ TableCell,
+ TableColumn,
+ TableHeader,
+ TableRow,
+ Tabs,
+ Tooltip,
+ useDisclosure,
+} from "@heroui/react";
+import React, { useEffect } from "react";
+import { useRouter } from "next/navigation";
+
+import EditActionModal from "@/components/modals/actions/edit";
+import DeleteActionModal from "@/components/modals/actions/delete";
+import AddActionModal from "@/components/modals/actions/add";
+import CreateFailurePipelineModal from "@/components/modals/failurePipelines/create";
+import DeleteFailurePipelineModal from "@/components/modals/failurePipelines/delete";
+import EditFailurePipelineModal from "@/components/modals/failurePipelines/edit";
+import UpdateFlowFailurePipelineActions from "@/lib/fetch/flow/PUT/UpdateFailurePipelineActions";
+import CopyActionModal from "@/components/modals/actions/copy";
+import UpgradeActionModal from "@/components/modals/actions/upgrade";
+import CopyActionToDifferentFlowModal from "@/components/modals/actions/transferCopy";
+
+export default function FlowFailurePipelines({
+ projects,
+ flows,
+ flow,
+ runners,
+ user,
+ canEdit,
+ settings,
+}: {
+ projects: any;
+ flows: any;
+ flow: any;
+ runners: any;
+ user: any;
+ canEdit: boolean;
+ settings: any;
+}) {
+ const router = useRouter();
+
+ const [targetAction, setTargetAction] = React.useState({} as any);
+ const [updatedAction, setUpdatedAction] = React.useState({} as any);
+
+ const [showDefaultParams, setShowDefaultParams] = React.useState(false);
+
+ const [failurePipelines, setFailurePipelines] = React.useState([] as any);
+ const [targetFailurePipeline, setTargetFailurePipeline] = React.useState(
+ {} as any,
+ );
+
+ const [failurePipelineTab, setFailurePipelineTab] =
+ React.useState("add-pipeline");
+
+ const createFlowFailurePipelineModal = useDisclosure();
+ const editFlowFailurePipelineModal = useDisclosure();
+ const deleteFailurePipelineModal = useDisclosure();
+ const addFlowFailurePipelineActionModal = useDisclosure();
+ const editFlowFailurePipelineActionModal = useDisclosure();
+ const deleteFlowFailurePipelineActionModal = useDisclosure();
+ const copyFlowFailurePipelineActionModal = useDisclosure();
+ const upgradeFlowFailurePipelineActionModal = useDisclosure();
+ const copyActionToDifferentFlowModal = useDisclosure();
+ const copyFailurePipelineActionToDifferentFlowModal = useDisclosure();
+
+ const [expandedParams, setExpandedParams] = React.useState([] as any);
+
+ useEffect(() => {
+ if (flow.failure_pipelines !== null) {
+ setFailurePipelines(flow.failure_pipelines);
+
+ if (failurePipelineTab === "add-pipeline") {
+ setFailurePipelineTab(flow.failure_pipelines[0]?.id || "add-pipeline");
+ }
+ }
+ }, [flow]);
+
+ const handleFailurePipelineTabChange = (key: any) => {
+ setFailurePipelineTab(key);
+ };
+
+ // function to get action from clipboard
+ const getClipboardAction = async () => {
+ try {
+ const clipboardText = await navigator.clipboard.readText();
+ const parsedAction = JSON.parse(clipboardText);
+
+ if (parsedAction && parsedAction.id && parsedAction.plugin) {
+ return parsedAction;
+ } else {
+ return null;
+ }
+ } catch {
+ return null;
+ }
+ };
+
+ const SortableItem = ({ action }: { action: any }) => {
+ const { attributes, listeners, setNodeRef, transform, transition } =
+ useSortable({ id: action.id });
+
+ const style = {
+ transform: CSS.Transform.toString(transform),
+ transition,
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {action.custom_name
+ ? action.custom_name
+ : action.name}
+
+
+ Vers. {action.version}
+
+
+ {action.active ? "Active" : "Disabled"}
+
+ {flow.failure_pipeline_id !== "" ||
+ (flow.failure_pipeline_id !== null &&
+ !flow.failure_pipelines.some(
+ (pipeline: any) =>
+ pipeline.id === action.failure_pipeline_id ||
+ (pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
+ )),
+ ) && (
+
+ No Failure Pipeline Assigned
+
+ ))}
+
+
+ {action.custom_description
+ ? action.custom_description
+ : action.description}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ onPress={() => {
+ navigator.clipboard.writeText(
+ JSON.stringify(action),
+ );
+ addToast({
+ title: "Action",
+ description: "Action copied to clipboard!",
+ color: "success",
+ variant: "flat",
+ });
+ }}
+ >
+ Clipboard
+
+
+ }
+ onPress={() => {
+ setTargetAction(action);
+ setTargetFailurePipeline(
+ flow.failure_pipelines.filter(
+ (pipeline: any) =>
+ pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
+ ),
+ )[0],
+ );
+ copyFlowFailurePipelineActionModal.onOpen();
+ }}
+ >
+ Local
+
+
+ }
+ onPress={() => {
+ // if action is in an failure pipeline, open the edit modal
+ if (
+ flow.failure_pipelines.some(
+ (pipeline: any) =>
+ pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
+ ),
+ )
+ ) {
+ setTargetAction(action);
+ setTargetFailurePipeline(
+ flow.failure_pipelines.filter(
+ (pipeline: any) =>
+ pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
+ ),
+ )[0],
+ );
+ copyFailurePipelineActionToDifferentFlowModal.onOpen();
+ } else {
+ setTargetAction(action);
+ copyActionToDifferentFlowModal.onOpen();
+ }
+ }}
+ >
+ Transfer
+
+
+
+ {
+ setTargetAction(action);
+ setTargetFailurePipeline(
+ flow.failure_pipelines.filter(
+ (pipeline: any) =>
+ pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
+ ),
+ )[0],
+ );
+ editFlowFailurePipelineActionModal.onOpen();
+ }}
+ >
+
+
+ {
+ setTargetAction(action.id);
+ setTargetFailurePipeline(
+ flow.failure_pipelines.filter(
+ (pipeline: any) =>
+ pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
+ ),
+ )[0],
+ );
+ deleteFlowFailurePipelineActionModal.onOpen();
+ }}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {action.active ? "Active" : "Disabled"}
+
+
+ Vers. {action.version}
+
+ {flow.failure_pipeline_id !== "" ||
+ (flow.failure_pipeline_id !== null &&
+ !flow.failure_pipelines.some(
+ (pipeline: any) =>
+ pipeline.id === action.failure_pipeline_id ||
+ (pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
+ )),
+ ) && (
+
+ No Failure Pipeline Assigned
+
+ ))}
+
+ {action.update_available && (
+
+ }
+ variant="flat"
+ onPress={() => {
+ setTargetAction(action);
+ setUpdatedAction(action.updated_action);
+ setTargetFailurePipeline(
+ flow.failure_pipelines.filter(
+ (pipeline: any) =>
+ pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
+ ),
+ )[0],
+ );
+ upgradeFlowFailurePipelineActionModal.onOpen();
+ }}
+ >
+ Upgrade
+
+ }
+ title={`Update to version ${action.update_version} available`}
+ variant="faded"
+ />
+ )}
+
+
+
+
+ Name
+ Value
+
+
+
+ ID
+
+
+ {action.id}
+
+
+
+
+ Plugin
+ {action.plugin}
+
+
+ Plugin Name
+ {action.name}
+
+
+ Plugin Description
+ {action.description}
+
+
+ Failure Pipeline
+
+ {flow.failure_pipeline_id === "" ||
+ flow.failure_pipeline_id === null ? (
+ flow.failure_pipelines.filter(
+ (pipeline: any) =>
+ pipeline.id === action.failure_pipeline_id,
+ )[0]?.name ||
+ action.failure_pipeline_id ||
+ "None"
+ ) : (
+
+ Overwritten by Flow Setting
+
+ )}
+
+
+
+
+
+ {action.params.length > 0 && (
+
+
+
+ Show default parameters
+
+
+
+
+ Key
+ Value
+ Note
+
+
+ {action.params
+ .filter(
+ (param: any) =>
+ showDefaultParams ||
+ param.value !== param.default,
+ )
+ .map((param: any, index: number) => (
+
+ {param.key}
+
+ {param.type === "password"
+ ? "••••••••"
+ : param.value}
+
+
+ {param.type === "password" &&
+ param.value != "" ? (
+
+ Encrypted
+
+ ) : (
+ ""
+ )}
+
+
+ ))}
+
+
+
+ )}
+ {action.condition.selected_action_id !== "" && (
+
+
+
Options
+
+ Cancel {" "}
+ Execution if conditions match and dont start any
+ following action.
+
+
+
+
+
+
+ a.id === action.condition.selected_action_id,
+ )[0]?.icon
+ }
+ width={26}
+ />
+
+
+
+
+ {flow.actions.filter(
+ (a: any) =>
+ a.id === action.condition.selected_action_id,
+ )[0]?.custom_name ||
+ flow.actions.filter(
+ (a: any) =>
+ a.id ===
+ action.condition.selected_action_id,
+ )[0]?.name ||
+ action.condition.selected_action_id}
+
+
+
+ {flow.actions.filter(
+ (a: any) =>
+ a.id === action.condition.selected_action_id,
+ )[0]?.custom_description ||
+ flow.actions.filter(
+ (a: any) =>
+ a.id === action.condition.selected_action_id,
+ )[0]?.description ||
+ "No description available"}
+
+
+
+
+
+ Key
+ Type
+ Value
+ Logic
+
+
+ {action.condition.condition_items.map(
+ (condition: any, index: number) => (
+
+ {condition.condition_key}
+
+ {condition.condition_type}
+
+
+ {condition.condition_value}
+
+
+ {condition.condition_logic === "and"
+ ? "&"
+ : "or"}
+
+
+ ),
+ )}
+
+
+
+ )}
+
+
+
+
+
+
+ );
+ };
+
+ const handleDragEndPipeline = (pipeline: any, event: any) => {
+ const { active, over } = event;
+
+ if (active.id !== over.id) {
+ const items = [...pipeline.actions];
+ const oldIndex = items.findIndex((item: any) => item.id === active.id);
+ const newIndex = items.findIndex((item: any) => item.id === over.id);
+
+ const newArray = arrayMove(items, oldIndex, newIndex);
+
+ updateFlowFailurePipelineActions(pipeline, newArray);
+ }
+ };
+
+ function updateFlowFailurePipelineActions(pipeline: any, actions: any) {
+ UpdateFlowFailurePipelineActions(flow.id, pipeline.id, actions)
+ .then(() => {
+ router.refresh();
+ addToast({
+ title: "Flow",
+ description:
+ "Flow failure pipeline actions order updated successfully.",
+ color: "success",
+ variant: "flat",
+ });
+ })
+ .catch(() => {
+ router.refresh();
+ addToast({
+ title: "Flow",
+ description: "Failed to update flow failure pipeline actions order.",
+ color: "danger",
+ variant: "flat",
+ });
+ });
+ }
+
+ return (
+
+
+ With failure pipelines you have the ability to send notifications or
+ trigger any other action if a specific action or the whole execution
+ failed.
+
+
+
+ {failurePipelines.map((pipeline: any) => (
+
+
+
+
+
+
+
+
{pipeline.name}
+
+
+ {pipeline.exec_parallel ? "Parallel" : "Sequential"}
+
+
+ action.failure_pipeline_id ===
+ pipeline.id,
+ ).length > 0
+ ? "success"
+ : "danger"
+ }
+ radius="sm"
+ size="sm"
+ variant="flat"
+ >
+ {flow.failure_pipeline_id === pipeline.id
+ ? "Assigned to Flow"
+ : flow.actions.filter(
+ (action: any) =>
+ action.failure_pipeline_id ===
+ pipeline.id,
+ ).length > 0
+ ? "Assigned on Step"
+ : "Not Assigned"}
+
+
+
+
+ {pipeline.id}
+
+
+
+
+
+ }
+ variant="solid"
+ onPress={() => {
+ setTargetFailurePipeline(pipeline);
+ addFlowFailurePipelineActionModal.onOpen();
+ }}
+ />
+
+
+
+ }
+ variant="light"
+ onPress={async () => {
+ const parsedAction = await getClipboardAction();
+
+ if (parsedAction) {
+ setTargetAction(parsedAction);
+ setTargetFailurePipeline(pipeline);
+ copyFlowFailurePipelineActionModal.onOpen();
+ } else {
+ addToast({
+ title: "Flow",
+ description: "No action found in clipboard.",
+ color: "danger",
+ variant: "flat",
+ });
+ }
+ }}
+ />
+
+
+
+ }
+ variant="light"
+ onPress={() => {
+ setTargetFailurePipeline(pipeline);
+ editFlowFailurePipelineModal.onOpen();
+ }}
+ />
+
+
+
+ }
+ variant="light"
+ onPress={() => {
+ setTargetFailurePipeline(pipeline.id);
+ deleteFailurePipelineModal.onOpen();
+ }}
+ />
+
+
+
+
+
+
+ handleDragEndPipeline(pipeline, event)}
+ >
+
+
+ {pipeline.actions !== null &&
+ pipeline.actions.length > 0 &&
+ pipeline.actions.map((action: any) => (
+
+ ))}
+
+
+
+
+
+
+ ))}
+ {
+ createFlowFailurePipelineModal.onOpen();
+ }}
+ >
+
+
+ }
+ />
+
+
+ {flow.failure_pipelines !== null &&
+ flow.failure_pipelines.length === 0 && (
+
+
+ No failure pipelines defined.
+
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/services/frontend/components/flows/flow/heading.tsx b/services/frontend/components/flows/flow/heading.tsx
index 6c76e35c..5073086d 100644
--- a/services/frontend/components/flows/flow/heading.tsx
+++ b/services/frontend/components/flows/flow/heading.tsx
@@ -57,7 +57,6 @@ export default function FlowHeading({
}
@@ -78,6 +78,25 @@ export default function FlowTabs({
user={user}
/>
+
+
+ Failure Pipelines
+
+ }
+ >
+
+
diff --git a/services/frontend/components/projects/list.tsx b/services/frontend/components/projects/list.tsx
index e9545b37..bd0ada08 100644
--- a/services/frontend/components/projects/list.tsx
+++ b/services/frontend/components/projects/list.tsx
@@ -6,6 +6,7 @@ import {
ButtonGroup,
Card,
CardBody,
+ CardFooter,
Chip,
Dropdown,
DropdownItem,
@@ -141,7 +142,7 @@ export function ProjectsList({ projects, pending_projects, user }: any) {
router.push(`/projects/${project.id}`);
}}
>
-
+
-
-
{project.name}
-
- {project.disabled ? "Disabled" : "Enabled"}
-
-
+
{project.name}
{project.description}
-
-
-
-
-
-
-
-
- }
- onPress={() => copyProjectIDtoClipboard(project.id)}
- >
- Copy ID
-
-
- }
- onPress={() => {
- setTargetProject(project);
- editProjectModal.onOpen();
- }}
- >
- Edit
-
-
- }
- onPress={() => {
- setTargetProject(project);
- deleteProjectModal.onOpen();
- }}
- >
- Delete
-
-
-
+
+ {project.disabled ? "Disabled" : "Enabled"}
+
+
+
+ Created At:{" "}
+ {new Date(project.created_at).toLocaleString() || "Unknown"}
+
+
+
+
+
+
+
+
+ }
+ onPress={() => copyProjectIDtoClipboard(project.id)}
+ >
+ Copy ID
+
+
+ }
+ onPress={() => {
+ setTargetProject(project);
+ editProjectModal.onOpen();
+ }}
+ >
+ Edit
+
+
+ }
+ onPress={() => {
+ setTargetProject(project);
+ deleteProjectModal.onOpen();
+ }}
+ >
+ Delete
+
+
+
+
))}
From f5159455b31608a64d1ccd69ff4d8d9198459dc2 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Tue, 19 Aug 2025 16:49:47 +0200
Subject: [PATCH 16/45] refactor: streamline FlowHeading and FlowSettings
components for improved layout and consistency
---
.../components/flows/flow/heading.tsx | 4 +-
.../components/flows/flow/settings.tsx | 133 +++++++++---------
.../frontend/components/flows/flow/tabs.tsx | 26 +---
3 files changed, 77 insertions(+), 86 deletions(-)
diff --git a/services/frontend/components/flows/flow/heading.tsx b/services/frontend/components/flows/flow/heading.tsx
index 5073086d..26123e4f 100644
--- a/services/frontend/components/flows/flow/heading.tsx
+++ b/services/frontend/components/flows/flow/heading.tsx
@@ -94,9 +94,7 @@ export default function FlowHeading({
onPress={() => {
editFlowModal.onOpen();
}}
- >
- Edit
-
+ />
{/* Mobile */}
diff --git a/services/frontend/components/flows/flow/settings.tsx b/services/frontend/components/flows/flow/settings.tsx
index 8a37eaf4..e6fc9e4a 100644
--- a/services/frontend/components/flows/flow/settings.tsx
+++ b/services/frontend/components/flows/flow/settings.tsx
@@ -84,14 +84,14 @@ export default function FlowSettings({
return (
<>
{error && }
-
-
-
Actions
-
-
-
-
-
+
+
+
+ Actions
+
+
+
+
Execution Strategy
Switch between parallel and sequential execution of
@@ -104,6 +104,7 @@ export default function FlowSettings({
}
placeholder="Select the execution strategy"
selectedKeys={[execParallel ? "parallel" : "sequential"]}
+ variant="bordered"
onSelectionChange={(e) => {
if (e.currentKey === "parallel") {
setExecParallel(true);
@@ -115,14 +116,12 @@ export default function FlowSettings({
Sequential
Parallel
-
-
-
+
+
-
-
-
-
+
+
+
Common Failure Pipeline
Execute an failure pipeline when actions during an
@@ -140,6 +139,7 @@ export default function FlowSettings({
}
placeholder="Select an failure pipeline"
selectedKeys={[failurePipelineID]}
+ variant="bordered"
onSelectionChange={(e) => {
if (e.currentKey === "none") {
setFailurePipelineID("");
@@ -153,56 +153,61 @@ export default function FlowSettings({
{pipeline.name}
))}
-
-
-
-
-
-
-
Executions
-
-
-
-
-
-
Schedule Every
-
- Schedule the flow to run every X minutes/hours/days.{" "}
-
- The system will always schedule two executions at the
- time. The second one will be scheduled base on the
- scheduled time of the first one.
-
-
- Enter 0 to disable the schedule.
-
-
-
-
-
- {
- setScheduleEveryUnit(e.currentKey);
- }}
- >
- Minutes
- Hours
- Days
- Weeks
-
+
+
+
+
+
+
+
+
+ Executions
+
+
+
+
+
+
Schedule Every
+
+ Schedule the flow to run every X minutes/hours/days.{" "}
+
+ The system will always schedule two executions at the
+ time. The second one will be scheduled base on the
+ scheduled time of the first one.
+
+
+ Enter 0 to disable the schedule.
+
+
+
+
+
+ {
+ setScheduleEveryUnit(e.currentKey);
+ }}
+ >
+ Minutes
+ Hours
+ Days
+ Weeks
+
+
-
-
-
-
-
+
+
+
+
+
+
-
- Stats
+
+ Info
}
>
+
+
-
-
- Info
-
- }
- >
-
-
From 12cd2fab3a164c81d3d96b9c28e5942e7af489c3 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Thu, 21 Aug 2025 11:28:43 +0200
Subject: [PATCH 17/45] feat: Update FlowHeading component to remove secondary
color from button
feat: Enhance FlowSettings component to disable inputs based on user role and edit permissions
feat: Add FlowActionDetails component for displaying action details in a drawer
style: Update Navbar component with new background and button radius
refactor: Simplify ProjectsList component by integrating new member management features and dropdown for project invitations
fix: Adjust Project component to ensure edit button is icon-only
fix: Update ProjectRunnerDetails component to correctly handle edit permissions
feat: Create ProjectMembers component for managing project members with modals for adding, editing, and removing members
delete: Remove unused UserTable component
fix: Update project tabs to use new ProjectMembers component
style: Enhance Search component button with new icon and full radius
feat: Implement ShineBorder component for animated border effects
chore: Bump version to 2.0.0 in site configuration
style: Add shine animation to Tailwind CSS configuration
---
.../components/flows/flow/actions.tsx | 667 +++++----------
.../flows/flow/failure-pipelines.tsx | 786 ++++++------------
.../components/flows/flow/heading.tsx | 1 -
.../components/flows/flow/settings.tsx | 6 +
.../components/modals/actions/details.tsx | 238 ++++++
services/frontend/components/navbar.tsx | 3 +-
.../frontend/components/projects/list.tsx | 234 ++++--
.../frontend/components/projects/project.tsx | 12 +-
.../projects/project/RunnerDetails.tsx | 6 +-
.../components/projects/project/members.tsx | 242 ++++++
.../projects/project/tables/UserTable.tsx | 284 -------
.../components/projects/project/tabs.tsx | 2 +-
.../frontend/components/search/search.tsx | 14 +-
.../frontend/components/ui/shine-border.tsx | 62 ++
services/frontend/config/site.ts | 2 +-
services/frontend/tailwind.config.ts | 12 +
16 files changed, 1196 insertions(+), 1375 deletions(-)
create mode 100644 services/frontend/components/modals/actions/details.tsx
create mode 100644 services/frontend/components/projects/project/members.tsx
delete mode 100644 services/frontend/components/projects/project/tables/UserTable.tsx
create mode 100644 services/frontend/components/ui/shine-border.tsx
diff --git a/services/frontend/components/flows/flow/actions.tsx b/services/frontend/components/flows/flow/actions.tsx
index c473b28d..b2f33b6a 100644
--- a/services/frontend/components/flows/flow/actions.tsx
+++ b/services/frontend/components/flows/flow/actions.tsx
@@ -9,29 +9,17 @@ import { CSS } from "@dnd-kit/utilities";
import { Icon } from "@iconify/react";
import {
addToast,
- Alert,
Button,
ButtonGroup,
Card,
CardBody,
- Checkbox,
+ CardFooter,
Chip,
- Divider,
Dropdown,
DropdownItem,
DropdownMenu,
DropdownTrigger,
- Snippet,
Spacer,
- Switch,
- Tab,
- Table,
- TableBody,
- TableCell,
- TableColumn,
- TableHeader,
- TableRow,
- Tabs,
Tooltip,
useDisclosure,
} from "@heroui/react";
@@ -45,6 +33,7 @@ import AddActionModal from "@/components/modals/actions/add";
import CopyActionModal from "@/components/modals/actions/copy";
import UpgradeActionModal from "@/components/modals/actions/upgrade";
import CopyActionToDifferentFlowModal from "@/components/modals/actions/transferCopy";
+import FlowActionDetails from "@/components/modals/actions/details";
export default function Actions({
projects,
@@ -67,8 +56,7 @@ export default function Actions({
const [targetAction, setTargetAction] = React.useState({} as any);
const [updatedAction, setUpdatedAction] = React.useState({} as any);
- const [showDefaultParams, setShowDefaultParams] = React.useState(false);
-
+ const viewFlowActionDetails = useDisclosure();
const editFlowActionsDetails = useDisclosure();
const addFlowActionModal = useDisclosure();
const editActionModal = useDisclosure();
@@ -108,458 +96,212 @@ export default function Actions({
return (
-
+ {
+ setTargetAction(action);
+ viewFlowActionDetails.onOpen();
+ }}
+ >
-
-
-
-
-
-
-
-
-
-
- {action.custom_name
- ? action.custom_name
- : action.name}
-
-
- Vers. {action.version}
-
-
- {action.active ? "Active" : "Disabled"}
-
- {flow.failure_pipeline_id !== "" ||
- (flow.failure_pipeline_id !== null &&
- !flow.failure_pipelines.some(
- (pipeline: any) =>
- pipeline.id === action.failure_pipeline_id ||
- (pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- )),
- ) && (
-
- No Failure Pipeline Assigned
-
- ))}
-
-
- {action.custom_description
- ? action.custom_description
- : action.description}
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
- onPress={() => {
- navigator.clipboard.writeText(
- JSON.stringify(action),
- );
- addToast({
- title: "Action",
- description: "Action copied to clipboard!",
- color: "success",
- variant: "flat",
- });
- }}
- >
- Clipboard
-
-
- }
- onPress={() => {
- setTargetAction(action);
- copyFlowActionModal.onOpen();
- }}
- >
- Local
-
-
- }
- onPress={() => {
- setTargetAction(action);
- copyActionToDifferentFlowModal.onOpen();
- }}
- >
- Transfer
-
-
-
- {
- setTargetAction(action);
- editActionModal.onOpen();
- }}
- >
-
-
- {
- setTargetAction(action.id);
- deleteActionModal.onOpen();
- }}
- >
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+ {action.custom_name ? action.custom_name : action.name}
+
+
+ {action.custom_description
+ ? action.custom_description
+ : action.description}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Vers. {action.version}
+
+
+ {action.active ? "Active" : "Disabled"}
+
+ {flow.failure_pipeline_id !== "" ||
+ (flow.failure_pipeline_id !== null &&
+ !flow.failure_pipelines.some(
+ (pipeline: any) =>
+ pipeline.id === action.failure_pipeline_id ||
+ (pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
+ )),
+ ) && (
+
+ No Failure Pipeline Assigned
+
+ ))}
+ {action.update_available && (
+
+ Upgrade Available
+
+ )}
+
+
+
+ {action.update_available && (
+
+ {
+ setTargetAction(action);
+ setUpdatedAction(action.updated_action);
+ upgradeFlowActionModal.onOpen();
+ }}
+ >
+
+
+
+ )}
+
+ {
+ setTargetAction(action);
+ viewFlowActionDetails.onOpen();
+ }}
>
- {action.active ? "Active" : "Disabled"}
-
-
+
+
+
+
+
+
+
+
+
+
+ }
+ onPress={() => {
+ navigator.clipboard.writeText(JSON.stringify(action));
+ addToast({
+ title: "Action",
+ description: "Action copied to clipboard!",
+ color: "success",
+ variant: "flat",
+ });
+ }}
+ >
+ Clipboard
+
+
+ }
+ onPress={() => {
+ setTargetAction(action);
+ copyFlowActionModal.onOpen();
+ }}
+ >
+ Local
+
+
+ }
+ onPress={() => {
+ setTargetAction(action);
+ copyActionToDifferentFlowModal.onOpen();
+ }}
+ >
+ Transfer
+
+
+
+
+ {
+ setTargetAction(action);
+ editActionModal.onOpen();
+ }}
>
- Vers. {action.version}
-
- {flow.failure_pipeline_id !== "" ||
- (flow.failure_pipeline_id !== null &&
- !flow.failure_pipelines.some(
- (pipeline: any) =>
- pipeline.id === action.failure_pipeline_id ||
- (pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- )),
- ) && (
-
- No Failure Pipeline Assigned
-
- ))}
-
-
- {action.update_available && (
-
-
- }
- variant="flat"
- onPress={() => {
- setTargetAction(action);
- setUpdatedAction(action.updated_action);
- upgradeFlowActionModal.onOpen();
- }}
- >
- Upgrade
-
- }
- title={`Update to version ${action.update_version} available`}
- variant="faded"
- />
-
- )}
-
-
-
- Name
- Value
-
-
-
- ID
-
-
- {action.id}
-
-
-
-
- Plugin
- {action.plugin}
-
-
- Plugin Name
- {action.name}
-
-
- Plugin Description
- {action.description}
-
-
- Failure Pipeline
-
- {flow.failure_pipeline_id === "" ||
- flow.failure_pipeline_id === null ? (
- flow.failure_pipelines.filter(
- (pipeline: any) =>
- pipeline.id === action.failure_pipeline_id,
- )[0]?.name ||
- action.failure_pipeline_id ||
- "None"
- ) : (
-
- Overwritten by Flow Setting
-
- )}
-
-
-
-
-
- {action.params.length > 0 && (
-
-
-
- Show default parameters
-
-
-
-
- Key
- Value
- Note
-
-
- {action.params
- .filter(
- (param: any) =>
- showDefaultParams ||
- param.value !== param.default,
- )
- .map((param: any, index: number) => (
-
- {param.key}
-
- {param.type === "password"
- ? "••••••••"
- : param.value}
-
-
- {param.type === "password" &&
- param.value != "" ? (
-
- Encrypted
-
- ) : (
- ""
- )}
-
-
- ))}
-
-
-
- )}
- {action.condition.selected_action_id !== "" && (
-
-
-
Options
-
- Cancel {" "}
- Execution if conditions match and dont start any
- following action.
-
-
-
-
-
-
- a.id === action.condition.selected_action_id,
- )[0]?.icon
- }
- width={26}
- />
-
-
-
-
- {flow.actions.filter(
- (a: any) =>
- a.id === action.condition.selected_action_id,
- )[0]?.custom_name ||
- flow.actions.filter(
- (a: any) =>
- a.id ===
- action.condition.selected_action_id,
- )[0]?.name ||
- action.condition.selected_action_id}
-
-
-
- {flow.actions.filter(
- (a: any) =>
- a.id === action.condition.selected_action_id,
- )[0]?.custom_description ||
- flow.actions.filter(
- (a: any) =>
- a.id === action.condition.selected_action_id,
- )[0]?.description ||
- "No description available"}
-
-
-
-
-
- Key
- Type
- Value
- Logic
-
-
- {action.condition.condition_items.map(
- (condition: any, index: number) => (
-
- {condition.condition_key}
-
- {condition.condition_type}
-
-
- {condition.condition_value}
-
-
- {condition.condition_logic === "and"
- ? "&"
- : "or"}
-
-
- ),
- )}
-
-
-
- )}
-
-
+
+
+
+
+ {
+ setTargetAction(action.id);
+ deleteActionModal.onOpen();
+ }}
+ >
+
+
+
+
-
+
);
@@ -684,6 +426,11 @@ export default function Actions({
runners={runners}
user={user}
/>
+
{
if (flow.failure_pipelines !== null) {
setFailurePipelines(flow.failure_pipelines);
@@ -138,299 +124,204 @@ export default function FlowFailurePipelines({
return (
-
+ {
+ setTargetAction(action);
+ viewFlowActionDetails.onOpen();
+ }}
+ >
-
-
-
-
-
-
-
-
-
-
- {action.custom_name
- ? action.custom_name
- : action.name}
-
-
- Vers. {action.version}
-
-
- {action.active ? "Active" : "Disabled"}
-
- {flow.failure_pipeline_id !== "" ||
- (flow.failure_pipeline_id !== null &&
- !flow.failure_pipelines.some(
- (pipeline: any) =>
- pipeline.id === action.failure_pipeline_id ||
- (pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- )),
- ) && (
-
- No Failure Pipeline Assigned
-
- ))}
-
-
- {action.custom_description
- ? action.custom_description
- : action.description}
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
- onPress={() => {
- navigator.clipboard.writeText(
- JSON.stringify(action),
- );
- addToast({
- title: "Action",
- description: "Action copied to clipboard!",
- color: "success",
- variant: "flat",
- });
- }}
- >
- Clipboard
-
-
- }
- onPress={() => {
- setTargetAction(action);
- setTargetFailurePipeline(
- flow.failure_pipelines.filter(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )[0],
- );
- copyFlowFailurePipelineActionModal.onOpen();
- }}
- >
- Local
-
-
- }
- onPress={() => {
- // if action is in an failure pipeline, open the edit modal
- if (
- flow.failure_pipelines.some(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )
- ) {
- setTargetAction(action);
- setTargetFailurePipeline(
- flow.failure_pipelines.filter(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )[0],
- );
- copyFailurePipelineActionToDifferentFlowModal.onOpen();
- } else {
- setTargetAction(action);
- copyActionToDifferentFlowModal.onOpen();
- }
- }}
- >
- Transfer
-
-
-
- {
- setTargetAction(action);
- setTargetFailurePipeline(
- flow.failure_pipelines.filter(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )[0],
- );
- editFlowFailurePipelineActionModal.onOpen();
- }}
- >
-
-
- {
- setTargetAction(action.id);
- setTargetFailurePipeline(
- flow.failure_pipelines.filter(
- (pipeline: any) =>
- pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- ),
- )[0],
- );
- deleteFlowFailurePipelineActionModal.onOpen();
- }}
- >
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+ {action.custom_name ? action.custom_name : action.name}
+
+
+ {action.custom_description
+ ? action.custom_description
+ : action.description}
+
+
+
+
+
+
- {action.active ? "Active" : "Disabled"}
-
-
+
+
+
+
+
+
+
+
+ Vers. {action.version}
+
+
+ {action.active ? "Active" : "Disabled"}
+
+ {flow.failure_pipeline_id !== "" ||
+ (flow.failure_pipeline_id !== null &&
+ !flow.failure_pipelines.some(
+ (pipeline: any) =>
+ pipeline.id === action.failure_pipeline_id ||
+ (pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
+ )),
+ ) && (
+
+ No Failure Pipeline Assigned
+
+ ))}
+ {action.update_available && (
+
+ Upgrade Available
+
+ )}
+
+
+
+ {action.update_available && (
+
+ {
+ setTargetAction(action);
+ setUpdatedAction(action.updated_action);
+ setTargetFailurePipeline(
+ flow.failure_pipelines.filter(
+ (pipeline: any) =>
+ pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
+ ),
+ )[0],
+ );
+ upgradeFlowFailurePipelineActionModal.onOpen();
+ }}
+ >
+
+
+
+ )}
+
+ {
+ setTargetAction(action);
+ viewFlowActionDetails.onOpen();
+ }}
>
- Vers. {action.version}
-
- {flow.failure_pipeline_id !== "" ||
- (flow.failure_pipeline_id !== null &&
- !flow.failure_pipelines.some(
- (pipeline: any) =>
- pipeline.id === action.failure_pipeline_id ||
- (pipeline.actions !== null &&
- pipeline.actions.some(
- (pipelineAction: any) =>
- pipelineAction.id === action.id,
- )),
- ) && (
-
- No Failure Pipeline Assigned
-
- ))}
-
- {action.update_available && (
-
- }
- variant="flat"
- onPress={() => {
+
+
+
+
+
+
+
+
+
+
+
+ }
+ onPress={() => {
+ navigator.clipboard.writeText(JSON.stringify(action));
+ addToast({
+ title: "Action",
+ description: "Action copied to clipboard!",
+ color: "success",
+ variant: "flat",
+ });
+ }}
+ >
+ Clipboard
+
+
+ }
+ onPress={() => {
+ setTargetAction(action);
+ setTargetFailurePipeline(
+ flow.failure_pipelines.filter(
+ (pipeline: any) =>
+ pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
+ ),
+ )[0],
+ );
+ copyFlowFailurePipelineActionModal.onOpen();
+ }}
+ >
+ Local
+
+
+ }
+ onPress={() => {
+ // if action is in an failure pipeline, open the edit modal
+ if (
+ flow.failure_pipelines.some(
+ (pipeline: any) =>
+ pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
+ ),
+ )
+ ) {
setTargetAction(action);
- setUpdatedAction(action.updated_action);
setTargetFailurePipeline(
flow.failure_pipelines.filter(
(pipeline: any) =>
@@ -441,235 +332,71 @@ export default function FlowFailurePipelines({
),
)[0],
);
- upgradeFlowFailurePipelineActionModal.onOpen();
- }}
- >
- Upgrade
-
+ copyFailurePipelineActionToDifferentFlowModal.onOpen();
+ } else {
+ setTargetAction(action);
+ copyActionToDifferentFlowModal.onOpen();
+ }
+ }}
+ >
+ Transfer
+
+
+
+
+
- )}
-
- {
+ setTargetAction(action);
+ setTargetFailurePipeline(
+ flow.failure_pipelines.filter(
+ (pipeline: any) =>
+ pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
+ ),
+ )[0],
+ );
+ editFlowFailurePipelineActionModal.onOpen();
+ }}
>
-
-
- Name
- Value
-
-
-
- ID
-
-
- {action.id}
-
-
-
-
- Plugin
- {action.plugin}
-
-
- Plugin Name
- {action.name}
-
-
- Plugin Description
- {action.description}
-
-
- Failure Pipeline
-
- {flow.failure_pipeline_id === "" ||
- flow.failure_pipeline_id === null ? (
- flow.failure_pipelines.filter(
- (pipeline: any) =>
- pipeline.id === action.failure_pipeline_id,
- )[0]?.name ||
- action.failure_pipeline_id ||
- "None"
- ) : (
-
- Overwritten by Flow Setting
-
- )}
-
-
-
-
-
- {action.params.length > 0 && (
-
-
-
- Show default parameters
-
-
-
-
- Key
- Value
- Note
-
-
- {action.params
- .filter(
- (param: any) =>
- showDefaultParams ||
- param.value !== param.default,
- )
- .map((param: any, index: number) => (
-
- {param.key}
-
- {param.type === "password"
- ? "••••••••"
- : param.value}
-
-
- {param.type === "password" &&
- param.value != "" ? (
-
- Encrypted
-
- ) : (
- ""
- )}
-
-
- ))}
-
-
-
- )}
- {action.condition.selected_action_id !== "" && (
-
-
-
Options
-
- Cancel {" "}
- Execution if conditions match and dont start any
- following action.
-
-
-
-
-
-
- a.id === action.condition.selected_action_id,
- )[0]?.icon
- }
- width={26}
- />
-
-
-
-
- {flow.actions.filter(
- (a: any) =>
- a.id === action.condition.selected_action_id,
- )[0]?.custom_name ||
- flow.actions.filter(
- (a: any) =>
- a.id ===
- action.condition.selected_action_id,
- )[0]?.name ||
- action.condition.selected_action_id}
-
-
-
- {flow.actions.filter(
- (a: any) =>
- a.id === action.condition.selected_action_id,
- )[0]?.custom_description ||
- flow.actions.filter(
- (a: any) =>
- a.id === action.condition.selected_action_id,
- )[0]?.description ||
- "No description available"}
-
-
-
-
-
- Key
- Type
- Value
- Logic
-
-
- {action.condition.condition_items.map(
- (condition: any, index: number) => (
-
- {condition.condition_key}
-
- {condition.condition_type}
-
-
- {condition.condition_value}
-
-
- {condition.condition_logic === "and"
- ? "&"
- : "or"}
-
-
+
+
+
+
+ {
+ setTargetAction(action.id);
+ setTargetFailurePipeline(
+ flow.failure_pipelines.filter(
+ (pipeline: any) =>
+ pipeline.actions !== null &&
+ pipeline.actions.some(
+ (pipelineAction: any) =>
+ pipelineAction.id === action.id,
),
- )}
-
-
-
- )}
-
-
+ )[0],
+ );
+ deleteFlowFailurePipelineActionModal.onOpen();
+ }}
+ >
+
+
+
+
-
+
);
@@ -937,6 +664,11 @@ export default function FlowFailurePipelines({
runners={runners}
user={user}
/>
+
}
variant="flat"
onPress={() => {
diff --git a/services/frontend/components/flows/flow/settings.tsx b/services/frontend/components/flows/flow/settings.tsx
index e6fc9e4a..e1eff0fc 100644
--- a/services/frontend/components/flows/flow/settings.tsx
+++ b/services/frontend/components/flows/flow/settings.tsx
@@ -183,12 +183,18 @@ export default function FlowSettings({
+
+ {() => (
+ <>
+
+
+
+
+
+
+
+
+ {action.custom_name || action.name}
+
+
+
+ {action.custom_description || action.description}
+
+
+
+
+
+
+
+
Plugin
+
{action.plugin}
+
+
+
Plugin Name
+
{action.name}
+
+
+
+ Plugin Description
+
+
+ {action.description}
+
+
+
+
+ Failure Pipeline
+
+
+ {flow.failure_pipeline_id === "" ||
+ flow.failure_pipeline_id === null ? (
+ flow.failure_pipelines.filter(
+ (pipeline: any) =>
+ pipeline.id === action.failure_pipeline_id,
+ )[0]?.name ||
+ action.failure_pipeline_id ||
+ "None"
+ ) : (
+
+ Overwritten by Flow Setting
+
+ )}
+
+
+
+ {action.params.length > 0 && (
+ <>
+
+
+
Parameters
+
+ Show default parameters
+
+
+
+
+ Key
+ Value
+ Note
+
+
+ {action.params
+ .filter(
+ (param: any) =>
+ showDefaultParams || param.value !== param.default,
+ )
+ .map((param: any, index: number) => (
+
+ {param.key}
+
+ {param.type === "password"
+ ? "••••••••"
+ : param.value}
+
+
+ {param.type === "password" &&
+ param.value != "" ? (
+ Encrypted
+ ) : (
+ ""
+ )}
+
+
+ ))}
+
+
+ >
+ )}
+
+ {action.condition.selected_action_id !== "" && (
+ <>
+
+ Conditions
+
+
Options
+
+ Cancel {" "}
+ Execution if conditions match and dont start any following
+ action.
+
+
+
+
+
+ a.id === action.condition.selected_action_id,
+ )[0]?.icon
+ }
+ width={26}
+ />
+
+
+
+
+ {flow.actions.filter(
+ (a: any) =>
+ a.id === action.condition.selected_action_id,
+ )[0]?.custom_name ||
+ flow.actions.filter(
+ (a: any) =>
+ a.id === action.condition.selected_action_id,
+ )[0]?.name ||
+ action.condition.selected_action_id}
+
+
+
+ {flow.actions.filter(
+ (a: any) =>
+ a.id === action.condition.selected_action_id,
+ )[0]?.custom_description ||
+ flow.actions.filter(
+ (a: any) =>
+ a.id === action.condition.selected_action_id,
+ )[0]?.description ||
+ "No description available"}
+
+
+
+
+
+ Key
+ Type
+ Value
+ Logic
+
+
+ {action.condition.condition_items.map(
+ (condition: any, index: number) => (
+
+ {condition.condition_key}
+ {condition.condition_type}
+ {condition.condition_value}
+
+ {condition.condition_logic === "and" ? "&" : "or"}
+
+
+ ),
+ )}
+
+
+ >
+ )}
+
+ >
+ )}
+
+
+ );
+}
diff --git a/services/frontend/components/navbar.tsx b/services/frontend/components/navbar.tsx
index 4c7da730..a3f925a3 100644
--- a/services/frontend/components/navbar.tsx
+++ b/services/frontend/components/navbar.tsx
@@ -66,6 +66,7 @@ export const Navbar = ({
return (
diff --git a/services/frontend/components/projects/list.tsx b/services/frontend/components/projects/list.tsx
index bd0ada08..11f45734 100644
--- a/services/frontend/components/projects/list.tsx
+++ b/services/frontend/components/projects/list.tsx
@@ -6,7 +6,6 @@ import {
ButtonGroup,
Card,
CardBody,
- CardFooter,
Chip,
Dropdown,
DropdownItem,
@@ -24,11 +23,27 @@ import EditProjectModal from "@/components/modals/projects/edit";
import AcceptProjectInvite from "@/lib/fetch/project/PUT/AcceptProjectInvite";
import DeclineProjectInvite from "@/lib/fetch/project/PUT/DeclineProjectInvite";
import canEditProject from "@/lib/functions/canEditProject";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
+
+import { ShineBorder } from "../ui/shine-border";
export function ProjectsList({ projects, pending_projects, user }: any) {
const router = useRouter();
+ const { refreshProjects } = useRefreshCache();
const [targetProject, setTargetProject] = useState({});
+
+ // project invitation button
+ const [selectedOption, setSelectedOption] = useState("accept");
+ const descriptionsMap = {
+ accept: "Accept the project invitation.",
+ decline: "Decline the project invitation.",
+ };
+ const labelsMap = {
+ accept: "Accept Invite",
+ decline: "Decline Invite",
+ };
+
const newProjectModal = useDisclosure();
const editProjectModal = useDisclosure();
const deleteProjectModal = useDisclosure();
@@ -52,6 +67,10 @@ export function ProjectsList({ projects, pending_projects, user }: any) {
}
};
+ function inviteSelectionChange(e: any) {
+ setSelectedOption(e.currentKey);
+ }
+
async function declineProjectInvite(projectId: string) {
const res = (await DeclineProjectInvite(projectId)) as any;
@@ -160,93 +179,95 @@ export function ProjectsList({ projects, pending_projects, user }: any) {
-
- {project.disabled ? "Disabled" : "Enabled"}
-
-
-
-
-
- Created At:{" "}
- {new Date(project.created_at).toLocaleString() || "Unknown"}
-
-
-
-
-
-
-
-
- }
- onPress={() => copyProjectIDtoClipboard(project.id)}
- >
- Copy ID
-
-
- }
- onPress={() => {
- setTargetProject(project);
- editProjectModal.onOpen();
- }}
+
+
- Edit
-
-
- }
- onPress={() => {
- setTargetProject(project);
- deleteProjectModal.onOpen();
- }}
+ {project.disabled ? "Disabled" : "Enabled"}
+
+
- Delete
-
-
-
-
+
+
+
+
+
+
+
+ }
+ onPress={() => copyProjectIDtoClipboard(project.id)}
+ >
+ Copy ID
+
+
+ }
+ onPress={() => {
+ setTargetProject(project);
+ editProjectModal.onOpen();
+ }}
+ >
+ Edit
+
+
+ }
+ onPress={() => {
+ setTargetProject(project);
+ deleteProjectModal.onOpen();
+ }}
+ >
+ Delete
+
+
+
+
+
+
))}
{pending_projects.length > 0 && (
<>
-
- Project Invitations
+
+ Pending Invitations
{pending_projects.map((project: any) => (
+
@@ -267,25 +288,60 @@ export function ProjectsList({ projects, pending_projects, user }: any) {
-
+
{
- declineProjectInvite(project.id);
- }}
- >
-
- Decline Invite
-
- {
- acceptProjectInvite(project.id);
+ if (selectedOption === "accept") {
+ acceptProjectInvite(project.id);
+ } else if (selectedOption === "decline") {
+ declineProjectInvite(project.id);
+ }
+
+ refreshProjects(); // Refresh SWR cache instead of router
}}
>
-
- Accept Invite
+ {labelsMap[selectedOption]}
+
+
+
+
+
+
+
+
+ }
+ >
+ {labelsMap["accept"]}
+
+
+ }
+ >
+ {labelsMap["decline"]}
+
+
+
diff --git a/services/frontend/components/projects/project.tsx b/services/frontend/components/projects/project.tsx
index 7e1f9f34..aea306d2 100644
--- a/services/frontend/components/projects/project.tsx
+++ b/services/frontend/components/projects/project.tsx
@@ -44,6 +44,7 @@ export default function Project({
}
variant="flat"
onPress={() => editProjectModal.onOpen()}
- >
- Edit
-
+ />
@@ -104,7 +103,12 @@ export default function Project({
-
{flows.length}
+
+ {
+ flows.filter((f: any) => f.project_id === project.id)
+ .length
+ }
+
Flows
diff --git a/services/frontend/components/projects/project/RunnerDetails.tsx b/services/frontend/components/projects/project/RunnerDetails.tsx
index 415b8ee7..2e74fb4a 100644
--- a/services/frontend/components/projects/project/RunnerDetails.tsx
+++ b/services/frontend/components/projects/project/RunnerDetails.tsx
@@ -204,7 +204,11 @@ export default function ProjectRunnerDetails({
m.user_id === user.id) &&
+ project.members.filter((m: any) => m.user_id === user.id)[0].role ===
+ "Owner"
+ ) {
+ return true;
+ }
+
+ if (project.disabled) {
+ return true;
+ }
+
+ return false;
+ }
+
+ return (
+
+
+
+
+
+
Members
+
+ {project.members.length} Members
+
+
+
+
+
+ }
+ variant="solid"
+ onPress={() => addProjectMemberModal.onOpen()}
+ />
+
+
+ {checkLeaveProjectDisabled() ? (
+
+
+ }
+ variant="flat"
+ onPress={() => transferOwnershipModal.onOpen()}
+ />
+
+ ) : (
+
+
+ }
+ variant="ghost"
+ onPress={() => leaveProjectModal.onOpen()}
+ />
+
+ )}
+
+
+
+
+
+
+ {project.members.map((member: any) => (
+
+
+
+
+ {member.username}
+ {member.user_id === user.id && (
+
+ You
+
+ )}
+
+ }
+ >
+ {member.user_id}
+
+
+
+
+
+
+ Invite: {member.invite_pending ? "Pending" : "Accepted"}
+
+
+ Invited At: {new Date(member.invited_at).toLocaleString()}
+
+
+
+
+ {
+ setTargetUser(member);
+ editProjectMemberModal.onOpen();
+ }}
+ >
+
+
+
+
+ {
+ setTargetUser(member);
+ deleteProjectMemberModal.onOpen();
+ }}
+ >
+
+
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+ );
+}
diff --git a/services/frontend/components/projects/project/tables/UserTable.tsx b/services/frontend/components/projects/project/tables/UserTable.tsx
deleted file mode 100644
index f806a11e..00000000
--- a/services/frontend/components/projects/project/tables/UserTable.tsx
+++ /dev/null
@@ -1,284 +0,0 @@
-import { Icon } from "@iconify/react";
-import {
- Button,
- ButtonGroup,
- Chip,
- Pagination,
- Table,
- TableBody,
- TableCell,
- TableColumn,
- TableHeader,
- TableRow,
- Tooltip,
- useDisclosure,
- User,
-} from "@heroui/react";
-import React from "react";
-import { useMediaQuery } from "usehooks-ts";
-
-import EditProjectMemberModal from "@/components/modals/projects/editMember";
-import LeaveProjectModal from "@/components/modals/projects/leave";
-import AddProjectMemberModal from "@/components/modals/projects/members";
-import ProjectTransferOwnership from "@/components/modals/projects/transferOwnership";
-import DeleteProjectMemberModal from "@/components/modals/projects/removeMember";
-import canEditProject from "@/lib/functions/canEditProject";
-
-const statusColorMap: any = {
- Owner: "danger",
- Editor: "primary",
- Viewer: "default",
-};
-
-export default function ProjectMembers({ project, settings, user }: any) {
- const addProjectMemberModal = useDisclosure();
- const editProjectMemberModal = useDisclosure();
- const leaveProjectModal = useDisclosure();
- const deleteProjectMemberModal = useDisclosure();
- const transferOwnershipModal = useDisclosure();
-
- const [targetUser, setTargetUser] = React.useState({});
-
- const isMobile = useMediaQuery("(max-width: 650px)");
-
- // pagination
- const [page, setPage] = React.useState(1);
- const rowsPerPage = 7;
- const pages = Math.ceil(project.members.length / rowsPerPage);
- const items = React.useMemo(() => {
- const start = (page - 1) * rowsPerPage;
- const end = start + rowsPerPage;
-
- return project.members.slice(start, end);
- }, [page, project]);
-
- const renderCell = React.useCallback((tableUser: any, columnKey: any) => {
- const cellValue = tableUser[columnKey];
-
- switch (columnKey) {
- case "name":
- return (
-
- {tableUser.username}
- {tableUser.user_id === user.id && (
-
- You
-
- )}
-
- }
- >
- {tableUser.user_id}
-
- );
- case "role":
- return (
-
- {cellValue}
-
- );
- case "invite_pending":
- return (
-
- {tableUser.invite_pending ? "Pending" : "Accepted"}
-
- );
- case "invited_at":
- return new Date(tableUser.invited_at).toLocaleString();
- case "actions":
- return (
-
-
- {
- setTargetUser(tableUser);
- editProjectMemberModal.onOpen();
- }}
- >
-
-
-
-
- {
- setTargetUser(tableUser);
- deleteProjectMemberModal.onOpen();
- }}
- >
-
-
-
-
- );
- default:
- return cellValue;
- }
- }, []);
-
- const topContent = React.useMemo(() => {
- return (
-
- {checkLeaveProjectDisabled() ? (
- }
- variant="flat"
- onPress={() => transferOwnershipModal.onOpen()}
- >
- {isMobile ? "" : "Transfer Ownership"}
-
- ) : (
-
- }
- variant="ghost"
- onPress={() => leaveProjectModal.onOpen()}
- >
- {isMobile ? "" : "Leave Project"}
-
- )}
- }
- onPress={() => addProjectMemberModal.onOpen()}
- >
- {isMobile ? "" : "Add Member"}
-
-
- );
- }, []);
-
- function checkLeaveProjectDisabled() {
- if (
- project.members.find((m: any) => m.user_id === user.id) &&
- project.members.filter((m: any) => m.user_id === user.id)[0].role ===
- "Owner"
- ) {
- return true;
- }
-
- if (project.disabled) {
- return true;
- }
-
- return false;
- }
-
- return (
- <>
-
- setPage(page)}
- />
-
- }
- classNames={{
- wrapper: "min-h-[222px]",
- }}
- topContent={topContent}
- >
-
-
- NAME
-
-
- ROLE
-
-
- Status
-
-
- Invited At
-
-
- ACTIONS
-
-
-
- {(item: any) => (
-
- {(columnKey) => (
- {renderCell(item, columnKey)}
- )}
-
- )}
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/services/frontend/components/projects/project/tabs.tsx b/services/frontend/components/projects/project/tabs.tsx
index 2b3358d7..d66b5a4e 100644
--- a/services/frontend/components/projects/project/tabs.tsx
+++ b/services/frontend/components/projects/project/tabs.tsx
@@ -4,7 +4,7 @@ import { Spacer, Tab, Tabs } from "@heroui/react";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import React from "react";
-import ProjectMembers from "@/components/projects/project/tables/UserTable";
+import ProjectMembers from "@/components/projects/project/members";
import ProjectTokens from "@/components/projects/project/tables/TokensTable";
import RunnersList from "@/components/runners/list";
diff --git a/services/frontend/components/search/search.tsx b/services/frontend/components/search/search.tsx
index ccd7f83d..63a16afd 100644
--- a/services/frontend/components/search/search.tsx
+++ b/services/frontend/components/search/search.tsx
@@ -796,16 +796,18 @@ export default function Search({
K}
- radius="sm"
+ radius="full"
size="md"
+ startContent={
+
+ }
variant="flat"
onPress={handleOpenCmdk}
>
-
Search...
{
+ /**
+ * Width of the border in pixels
+ * @default 1
+ */
+ borderWidth?: number;
+ /**
+ * Duration of the animation in seconds
+ * @default 14
+ */
+ duration?: number;
+ /**
+ * Color of the border, can be a single color or an array of colors
+ * @default "#000000"
+ */
+ shineColor?: string | string[];
+}
+
+/**
+ * Shine Border
+ *
+ * An animated background border effect component with configurable properties.
+ */
+export function ShineBorder({
+ borderWidth = 1,
+ duration = 14,
+ shineColor = "#000000",
+ className,
+ style,
+ ...props
+}: ShineBorderProps) {
+ return (
+
+ );
+}
diff --git a/services/frontend/config/site.ts b/services/frontend/config/site.ts
index 84d7501c..a2bda5b5 100644
--- a/services/frontend/config/site.ts
+++ b/services/frontend/config/site.ts
@@ -3,7 +3,7 @@ export type SiteConfig = typeof siteConfig;
export const siteConfig = {
name: "exFlow",
description: "exFlow is an workflow automation tool",
- version: "1.5.2",
+ version: "2.0.0",
navItems: [
{
label: "Dashboard",
diff --git a/services/frontend/tailwind.config.ts b/services/frontend/tailwind.config.ts
index 0b7866fa..87cace67 100644
--- a/services/frontend/tailwind.config.ts
+++ b/services/frontend/tailwind.config.ts
@@ -16,8 +16,20 @@ module.exports = {
animation: {
"border-beam": "border-beam calc(var(--duration)*1s) infinite linear",
gradient: "gradient 8s linear infinite",
+ shine: "shine var(--duration) infinite linear",
},
keyframes: {
+ shine: {
+ "0%": {
+ "background-position": "0% 0%",
+ },
+ "50%": {
+ "background-position": "100% 100%",
+ },
+ to: {
+ "background-position": "0% 0%",
+ },
+ },
"border-beam": {
"100%": {
"offset-distance": "100%",
From 60fc9ba53d4cba28b5d02ddd3cd5fe26cef70756 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Thu, 21 Aug 2025 11:49:02 +0200
Subject: [PATCH 18/45] refactor: remove PostCSS configuration and update
Tailwind setup
- Deleted the old PostCSS configuration file.
- Updated global CSS to import Tailwind and define custom animations.
- Refactored Tailwind configuration to remove unused animations and keyframes.
- Added new ShineBorder component for animated border effects.
- Created a new hero component using the heroui library.
- Introduced a new PostCSS configuration file using ES module syntax.
---
services/frontend/app/layout.tsx | 2 +-
.../components/admin/projects/list.tsx | 2 +-
.../frontend/components/auth/loginPage.tsx | 2 +-
.../frontend/components/auth/signupPage.tsx | 2 +-
.../execution/executionStepsAccordion.tsx | 4 +-
.../execution/executionStepsTable.tsx | 4 +-
.../frontend/components/magicui/particles.tsx | 114 +-
.../{ui => magicui}/shine-border.tsx | 0
.../frontend/components/modals/flows/edit.tsx | 2 +-
services/frontend/components/primitives.ts | 4 +-
.../frontend/components/projects/list.tsx | 10 +-
.../frontend/components/search/new-chip.tsx | 2 +-
.../frontend/components/search/popover.tsx | 2 +-
.../frontend/components/search/search.tsx | 8 +-
.../components/steps/minimal-row-steps.tsx | 6 +-
.../frontend/components/steps/row-steps.tsx | 6 +-
services/frontend/hero.ts | 5 +
services/frontend/package.json | 11 +-
services/frontend/pnpm-lock.yaml | 4181 ++++++++---------
services/frontend/postcss.config.js | 6 -
services/frontend/postcss.config.mjs | 7 +
services/frontend/styles/globals.css | 21 +-
services/frontend/tailwind.config.ts | 18 -
23 files changed, 2093 insertions(+), 2326 deletions(-)
rename services/frontend/components/{ui => magicui}/shine-border.tsx (100%)
create mode 100644 services/frontend/hero.ts
delete mode 100644 services/frontend/postcss.config.js
create mode 100644 services/frontend/postcss.config.mjs
diff --git a/services/frontend/app/layout.tsx b/services/frontend/app/layout.tsx
index 3b4042e6..914093ea 100644
--- a/services/frontend/app/layout.tsx
+++ b/services/frontend/app/layout.tsx
@@ -115,7 +115,7 @@ export default async function RootLayout({
userDetails={userDetails.success ? userDetails.data.user : {}}
/>
)}
- {children}
+ {children}
diff --git a/services/frontend/components/admin/projects/list.tsx b/services/frontend/components/admin/projects/list.tsx
index 204925ea..5b05399f 100644
--- a/services/frontend/components/admin/projects/list.tsx
+++ b/services/frontend/components/admin/projects/list.tsx
@@ -55,7 +55,7 @@ export function AdminProjectList({ projects }: any) {
case "icon":
return (
-
+
{currentLineNumber}
-
+
{new Date(
line.timestamp,
diff --git a/services/frontend/components/executions/execution/executionStepsTable.tsx b/services/frontend/components/executions/execution/executionStepsTable.tsx
index e345f690..0fe50fae 100644
--- a/services/frontend/components/executions/execution/executionStepsTable.tsx
+++ b/services/frontend/components/executions/execution/executionStepsTable.tsx
@@ -440,12 +440,12 @@ export function ExecutionStepsTable({
key={`${dataIndex}-${lineIndex}`}
className={`container flex items-start gap-3 py-0.3 hover:bg-default-100/50 transition-colors`}
>
-
+
{currentLineNumber}
-
+
{new Date(
line.timestamp,
diff --git a/services/frontend/components/magicui/particles.tsx b/services/frontend/components/magicui/particles.tsx
index f5ed89a0..f2ab0ee9 100644
--- a/services/frontend/components/magicui/particles.tsx
+++ b/services/frontend/components/magicui/particles.tsx
@@ -1,12 +1,18 @@
-/* eslint-disable no-undef */
"use client";
-import React, { useEffect, useRef, useState } from "react";
+import React, {
+ ComponentPropsWithoutRef,
+ useEffect,
+ useRef,
+ useState,
+} from "react";
-type MousePosition = {
+import { cn } from "@/lib/utils";
+
+interface MousePosition {
x: number;
y: number;
-};
+}
function MousePosition(): MousePosition {
const [mousePosition, setMousePosition] = useState({
@@ -15,13 +21,16 @@ function MousePosition(): MousePosition {
});
useEffect(() => {
+ // eslint-disable-next-line no-undef
const handleMouseMove = (event: MouseEvent) => {
setMousePosition({ x: event.clientX, y: event.clientY });
};
+ // eslint-disable-next-line no-undef
window.addEventListener("mousemove", handleMouseMove);
return () => {
+ // eslint-disable-next-line no-undef
window.removeEventListener("mousemove", handleMouseMove);
};
}, []);
@@ -29,7 +38,7 @@ function MousePosition(): MousePosition {
return mousePosition;
}
-type ParticlesProps = {
+interface ParticlesProps extends ComponentPropsWithoutRef<"div"> {
className?: string;
quantity?: number;
staticity?: number;
@@ -39,7 +48,8 @@ type ParticlesProps = {
color?: string;
vx?: number;
vy?: number;
-};
+}
+
function hexToRgb(hex: string): number[] {
hex = hex.replace("#", "");
@@ -50,7 +60,7 @@ function hexToRgb(hex: string): number[] {
.join("");
}
- const hexInt = Number.parseInt(hex, 16);
+ const hexInt = parseInt(hex, 16);
const red = (hexInt >> 16) & 255;
const green = (hexInt >> 8) & 255;
const blue = hexInt & 255;
@@ -58,7 +68,20 @@ function hexToRgb(hex: string): number[] {
return [red, green, blue];
}
-const Particles: React.FC = ({
+type Circle = {
+ x: number;
+ y: number;
+ translateX: number;
+ translateY: number;
+ size: number;
+ alpha: number;
+ targetAlpha: number;
+ dx: number;
+ dy: number;
+ magnetism: number;
+};
+
+export const Particles: React.FC = ({
className = "",
quantity = 100,
staticity = 50,
@@ -68,15 +91,23 @@ const Particles: React.FC = ({
color = "#ffffff",
vx = 0,
vy = 0,
+ ...props
}) => {
+ // eslint-disable-next-line no-undef
const canvasRef = useRef(null);
+ // eslint-disable-next-line no-undef
const canvasContainerRef = useRef(null);
+ // eslint-disable-next-line no-undef
const context = useRef(null);
- const circles = useRef([]);
+ const circles = useRef([]);
const mousePosition = MousePosition();
const mouse = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
const canvasSize = useRef<{ w: number; h: number }>({ w: 0, h: 0 });
+ // eslint-disable-next-line no-undef
const dpr = typeof window !== "undefined" ? window.devicePixelRatio : 1;
+ const rafID = useRef(null);
+ // eslint-disable-next-line no-undef
+ const resizeTimeout = useRef(null);
useEffect(() => {
if (canvasRef.current) {
@@ -84,10 +115,29 @@ const Particles: React.FC = ({
}
initCanvas();
animate();
- window.addEventListener("resize", initCanvas);
+
+ const handleResize = () => {
+ if (resizeTimeout.current) {
+ clearTimeout(resizeTimeout.current);
+ }
+ resizeTimeout.current = setTimeout(() => {
+ initCanvas();
+ }, 200);
+ };
+
+ // eslint-disable-next-line no-undef
+ window.addEventListener("resize", handleResize);
return () => {
- window.removeEventListener("resize", initCanvas);
+ if (rafID.current != null) {
+ // eslint-disable-next-line no-undef
+ window.cancelAnimationFrame(rafID.current);
+ }
+ if (resizeTimeout.current) {
+ clearTimeout(resizeTimeout.current);
+ }
+ // eslint-disable-next-line no-undef
+ window.removeEventListener("resize", handleResize);
};
}, [color]);
@@ -119,29 +169,24 @@ const Particles: React.FC = ({
}
};
- type Circle = {
- x: number;
- y: number;
- translateX: number;
- translateY: number;
- size: number;
- alpha: number;
- targetAlpha: number;
- dx: number;
- dy: number;
- magnetism: number;
- };
-
const resizeCanvas = () => {
if (canvasContainerRef.current && canvasRef.current && context.current) {
- circles.current.length = 0;
canvasSize.current.w = canvasContainerRef.current.offsetWidth;
canvasSize.current.h = canvasContainerRef.current.offsetHeight;
+
canvasRef.current.width = canvasSize.current.w * dpr;
canvasRef.current.height = canvasSize.current.h * dpr;
canvasRef.current.style.width = `${canvasSize.current.w}px`;
canvasRef.current.style.height = `${canvasSize.current.h}px`;
context.current.scale(dpr, dpr);
+
+ // Clear existing particles and create new ones with exact quantity
+ circles.current = [];
+ for (let i = 0; i < quantity; i++) {
+ const circle = circleParams();
+
+ drawCircle(circle);
+ }
}
};
@@ -152,9 +197,7 @@ const Particles: React.FC = ({
const translateY = 0;
const pSize = Math.floor(Math.random() * 2) + size;
const alpha = 0;
- const targetAlpha = Number.parseFloat(
- (Math.random() * 0.6 + 0.1).toFixed(1),
- );
+ const targetAlpha = parseFloat((Math.random() * 0.6 + 0.1).toFixed(1));
const dx = (Math.random() - 0.5) * 0.1;
const dy = (Math.random() - 0.5) * 0.1;
const magnetism = 0.1 + Math.random() * 4;
@@ -238,7 +281,7 @@ const Particles: React.FC = ({
canvasSize.current.h - circle.y - circle.translateY - circle.size, // distance from bottom edge
];
const closestEdge = edge.reduce((a, b) => Math.min(a, b));
- const remapClosestEdge = Number.parseFloat(
+ const remapClosestEdge = parseFloat(
remapValue(closestEdge, 0, 20, 0, 1).toFixed(2),
);
@@ -274,17 +317,20 @@ const Particles: React.FC = ({
const newCircle = circleParams();
drawCircle(newCircle);
- // update the circle position
}
});
- window.requestAnimationFrame(animate);
+ // eslint-disable-next-line no-undef
+ rafID.current = window.requestAnimationFrame(animate);
};
return (
-
+
);
};
-
-export default Particles;
diff --git a/services/frontend/components/ui/shine-border.tsx b/services/frontend/components/magicui/shine-border.tsx
similarity index 100%
rename from services/frontend/components/ui/shine-border.tsx
rename to services/frontend/components/magicui/shine-border.tsx
diff --git a/services/frontend/components/modals/flows/edit.tsx b/services/frontend/components/modals/flows/edit.tsx
index a5f516b7..e927d7e4 100644
--- a/services/frontend/components/modals/flows/edit.tsx
+++ b/services/frontend/components/modals/flows/edit.tsx
@@ -224,7 +224,7 @@ export default function EditFlowModal({
"group-data-[selected=true]:ml-6",
// pressed
"group-data-[pressed=true]:w-7",
- "group-data-[selected]:group-data-[pressed]:ml-4",
+ "group-data-selected:group-data-pressed:ml-4",
),
}}
isSelected={runnerLimit}
diff --git a/services/frontend/components/primitives.ts b/services/frontend/components/primitives.ts
index 472973cb..04b1f225 100644
--- a/services/frontend/components/primitives.ts
+++ b/services/frontend/components/primitives.ts
@@ -35,7 +35,7 @@ export const title = tv({
"pink",
"foreground",
],
- class: "bg-clip-text text-transparent bg-gradient-to-b",
+ class: "bg-clip-text text-transparent bg-linear-to-b",
},
],
});
@@ -44,7 +44,7 @@ export const subtitle = tv({
base: "w-full md:w-1/2 my-2 text-lg lg:text-xl text-default-600 block max-w-full",
variants: {
fullWidth: {
- true: "!w-full",
+ true: "w-full!",
},
},
defaultVariants: {
diff --git a/services/frontend/components/projects/list.tsx b/services/frontend/components/projects/list.tsx
index 11f45734..008ee6d2 100644
--- a/services/frontend/components/projects/list.tsx
+++ b/services/frontend/components/projects/list.tsx
@@ -25,7 +25,7 @@ import DeclineProjectInvite from "@/lib/fetch/project/PUT/DeclineProjectInvite";
import canEditProject from "@/lib/functions/canEditProject";
import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
-import { ShineBorder } from "../ui/shine-border";
+import { ShineBorder } from "../magicui/shine-border";
export function ProjectsList({ projects, pending_projects, user }: any) {
const router = useRouter();
@@ -165,14 +165,14 @@ export function ProjectsList({ projects, pending_projects, user }: any) {
-
+
{project.name}
{project.description}
@@ -272,14 +272,14 @@ export function ProjectsList({ projects, pending_projects, user }: any) {
-
+
{project.name}
diff --git a/services/frontend/components/search/new-chip.tsx b/services/frontend/components/search/new-chip.tsx
index c6b7fa37..31c62538 100644
--- a/services/frontend/components/search/new-chip.tsx
+++ b/services/frontend/components/search/new-chip.tsx
@@ -31,7 +31,7 @@ export const NewChip: React.FC<
{/* Category (Web) */}
{!isMobile && isEmpty(query) && (
-
+
Categories
{renderCategories()}
diff --git a/services/frontend/components/steps/minimal-row-steps.tsx b/services/frontend/components/steps/minimal-row-steps.tsx
index 913394f7..2d822372 100644
--- a/services/frontend/components/steps/minimal-row-steps.tsx
+++ b/services/frontend/components/steps/minimal-row-steps.tsx
@@ -223,7 +223,7 @@ const MinimalRowSteps = ({
>
{status === "complete" ? (
-
+
) : (
)}
@@ -235,7 +235,7 @@ const MinimalRowSteps = ({
{stepIdx < stepsCount - 1 && !hideProgressBars && (
(
>
{status === "complete" ? (
-
+
) : (
{stepIdx + 1}
)}
@@ -256,8 +256,8 @@ const RowSteps = React.forwardRef
(
>
=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/alert@2.2.19':
- resolution: {integrity: sha512-Qou8JxQy75rce9L4RA50zAJbEDVaQOHV1McWm0gJPBpKzDeN9sFSSyRy7UgKSDTQc5s3TVfQMZYrq2txY2HQlQ==}
+ '@heroui/alert@2.2.24':
+ resolution: {integrity: sha512-Yec/mykI3n14uJaCP4RTR6iXIa3cFsVF7dt51xFkb0X/h6fTIUiSwnH7hM7vacAHpq5letFcm5XNMj316R2PpA==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.19'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/aria-utils@2.2.16':
- resolution: {integrity: sha512-d4MuOSpn95RgxJloLc9mDfo162Z0/YtErr6CgXbIWNQfZL8AfBxUMCuhYS1KCUwBV6usitMf2XIW4zGEGtMkXA==}
+ '@heroui/aria-utils@2.2.21':
+ resolution: {integrity: sha512-6R01UEqgOOlD+MgizCQfsP2yK8e7RAHhWM/MtXHSCjWG7Ud+Ys1HlZPaH8+BB1P6UqtHZScZQevUFq975YJ57Q==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/autocomplete@2.3.20':
- resolution: {integrity: sha512-QlZ3AjGt/hXW0sJxK+x7XU+PNLam5HU1wYuaC9Q6TXabvh/2BcFncvCi0l3OShh5GYuiP2BTP3Ynb3pdd1+DAA==}
+ '@heroui/autocomplete@2.3.26':
+ resolution: {integrity: sha512-njdBN9mIM3zUJ2EvSjBBdm8tjRgL5FFQrsgR/OWCdLGui1n1A7h/bF6o5AWZkcDDX5jP1hsGZDtQ+28frorjtw==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/avatar@2.2.15':
- resolution: {integrity: sha512-8o5+PciEH/uCqlaJDmc06sHAYLFoTenQfpIzWTh4Z/ced3u3xT74ZKf/+q4DnezaA5uJA+nc3+LF3wWli6/o/g==}
+ '@heroui/avatar@2.2.20':
+ resolution: {integrity: sha512-wqbgEQQwEyG42EtpiVdy75JsHiJspC9bBusZYB+LIzV3hMO7Gt70rD4W6TShO+L7VA/S1UfHqGL06oYUC7K7ew==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/badge@2.2.12':
- resolution: {integrity: sha512-JVvsmgHzvNDHMSW0/51LaikjTIxm59dU7Bvgp6bN5MuWgMvdhVcrrBskyy98uk7B4i8yYEfzfKBOPU3apZGAug==}
+ '@heroui/badge@2.2.15':
+ resolution: {integrity: sha512-wdxMBH+FkfqPZrv2FP9aqenKG5EeOH2i9mSopMHP+o4ZaWW5lmKYqjN1lQ5DXCO4XaDtY4jOWEExp4UJ2e7rKg==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/breadcrumbs@2.2.15':
- resolution: {integrity: sha512-86/WSR21CRPiurb6OLiEPpQeZNPGWyNdpen3tpwT/4nC1U/9nOAw+Gt8uB8dO9Xze6wR4d1yqAIuSPGgVL7OPA==}
+ '@heroui/breadcrumbs@2.2.20':
+ resolution: {integrity: sha512-lH3MykNKF91bbgXRamtKhfnkzmMyfbqErWgnRVVH4j0ae5I8lWuWcmrDlOIrfhzQf+6xv6Mt2uUE2074FOwYmw==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/button@2.2.19':
- resolution: {integrity: sha512-9vpTYyGzadcLa2Toy1K0Aoa6hno2kH5S+Sc9Ruliim0MdoqXtdsD2i1Ywpgf2xp6bD6bTHsfb1uuspAYJRdxJA==}
+ '@heroui/button@2.2.24':
+ resolution: {integrity: sha512-PR4CZaDSSAGYPv7uUNRc9FAJkNtMgcNUdnD0qxQoJDQoB/C6LLLgROqc/iHaKX9aEH5JYIISbMxTIcJtY2Zk2A==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/calendar@2.2.19':
- resolution: {integrity: sha512-q9bSjSWa/NlJGnb/7n18bXXZbn2/oPAAnpgieLorUh/0XeW9mGgasa6OA3VC6q+GfA6MHNpdhe4MBN9jc5fwlA==}
+ '@heroui/calendar@2.2.24':
+ resolution: {integrity: sha512-zUJ/m8uAVEn53FcKN6B2a+BtjXAsSicu8M667aKyaGgVFwOTWgH5miFvD/xLyFu+gAF/LBrC6ysDQMdHdiKKBQ==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/card@2.2.18':
- resolution: {integrity: sha512-fgvOfmeEz3ri9ft2P45ycclsC0AeJxQnZey2JuF6G8ou7IOKYEO0najuW6PDs9h50tY5TLWl1fU5S7WMUzjEpw==}
+ '@heroui/card@2.2.23':
+ resolution: {integrity: sha512-oMmZNr2/mGp/S+Ct8iyzAp4H+tLuT3G0dgHyRie7txj8en79RAy+yRPBYdSt3OpIWM/Zv9un3Dnxgmi/UGCo+A==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/checkbox@2.3.18':
- resolution: {integrity: sha512-hTVCN2A4+lPt+JmsBzgVS5YNEyEu8NvdUDJ01NA3DNpIjAxV6RmiVl6HnRxECHt7xCzqk5inun/W38NOos756g==}
+ '@heroui/checkbox@2.3.24':
+ resolution: {integrity: sha512-H/bcpYGeWB9WFhkkOPojO4ONrz5GIMzfAMYdaKOUFtLVl7B9yVca7HaKdNryAFtNSBd/QQAm/an7gh/OFxIgew==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.3'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/chip@2.2.15':
- resolution: {integrity: sha512-c5omTTjpkydwN9L9LcA3ibxRfWhxYMjJkJwkDZkCY5T+FKItv0iRo2PX6+k13UOhQe+G03zwCJxgkQvAUZHU0A==}
+ '@heroui/chip@2.2.20':
+ resolution: {integrity: sha512-BTYXeMcSeBPOZEFk4MDGTrcML/NLYmQn+xdlSdiv9b2dM/gEq1hpTizt+kpvNH7kF6BSUxM6zJearIGUZ7gf5w==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/code@2.2.14':
- resolution: {integrity: sha512-mFHgSXi1XzP+B59QBpWk/6NOc2A8wToPWDEaPOJO65nNUZ0S7FHhZTUNVPxHRn3wy8RPclPUpLFicGggT5inQw==}
+ '@heroui/code@2.2.18':
+ resolution: {integrity: sha512-e8+5LoJw6GQs9ASlAjdHG/Ksgiu9AyPfmf6ElP0VNXuRbXEtiOO5gXJxxh81bxz05HQaQyL/mQZKqnxf+Zb6bA==}
peerDependencies:
- '@heroui/theme': '>=2.4.6'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/date-input@2.3.18':
- resolution: {integrity: sha512-G9RTgvu0L3DyqrmlqeaFN+xWcZaLgfAVJi8hh3tyP1K6VtlSi1+NfioeJ47HZabFy7balmQBioCK/Qg2iZqf3Q==}
+ '@heroui/date-input@2.3.24':
+ resolution: {integrity: sha512-K1OFu8vv3oEgQ9GV2ipB+tJOsU/0+DsKWDiKiAISMt4OXilybncm2SrR05M5D36BM0jm5gofnNN7geMYBbhngQ==}
peerDependencies:
- '@heroui/system': '>=2.4.10'
- '@heroui/theme': '>=2.4.9'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/date-picker@2.3.19':
- resolution: {integrity: sha512-v+mpWcO9XIknLbVFSdIgVQhFHjinO/ysmsh1lWtXN70GLcc959ip493dWaENx/9VdNFqt4XiB/0d16BBDghsrw==}
+ '@heroui/date-picker@2.3.25':
+ resolution: {integrity: sha512-UHnn/RDHF4vVZcJ54U8hArknYcmEGyeNbhRNVtXKcRWQgrA7gi/S5ng9m8Wi/j+SbWK7KiPdVSwlk/1PQr5Vdw==}
peerDependencies:
- '@heroui/system': '>=2.4.10'
- '@heroui/theme': '>=2.4.9'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/divider@2.2.13':
- resolution: {integrity: sha512-axoFh+eAdlmEPgu8RAbfEhRop/Bld/VuhCr7r7N/CBhCHTOz0H8ja/keYQAZr8Nnxn5s/Lx0NwMuPT0SZEi23A==}
+ '@heroui/divider@2.2.17':
+ resolution: {integrity: sha512-/6u3mo3TLGOsxYftuHUamfgDYZARsk7esKSxwEeSJ1ufIuo/+Z+yPpaTfe3WUvha0VuwTfyLN99+puqdoTU3zQ==}
peerDependencies:
- '@heroui/theme': '>=2.4.6'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/dom-animation@2.1.8':
- resolution: {integrity: sha512-88PwAmkF+lodZisF1OB3CuwNs+1sTB5eAfGvXZGUCO/rNZvGIL4KxmxuDM2odb0MJYklMU39+aqCEg/U+x2tEA==}
+ '@heroui/dom-animation@2.1.10':
+ resolution: {integrity: sha512-dt+0xdVPbORwNvFT5pnqV2ULLlSgOJeqlg/DMo97s9RWeD6rD4VedNY90c8C9meqWqGegQYBQ9ztsfX32mGEPA==}
peerDependencies:
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
- '@heroui/drawer@2.2.16':
- resolution: {integrity: sha512-g3kquuqvHF15KY2jStlEEE9cUpnxRyvrasyQQtVLjxfJwBPosl9Yp6vS6z+sYBhvgTZc5r66LpEOREumrSxvSQ==}
+ '@heroui/drawer@2.2.21':
+ resolution: {integrity: sha512-pYFWOyIqX1gmMOsFxEfajWFjX32O1jDvei7Q9eHs4AVVw7DaeWtQUYovM/6p8yRp//X/bxNQpUhMvEFaIc/8yQ==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/dropdown@2.3.19':
- resolution: {integrity: sha512-smSnLNM9s1f/l+0Z1J6nn6wcvfLCz/GRLRJLw09qnoUb+9pGWxsA1uZNRopB7oZOrD5VafGHR6bXy5iV7mfReQ==}
+ '@heroui/dropdown@2.3.24':
+ resolution: {integrity: sha512-xqvfCViiFW1jOqtRHvMT2mUe7FjTHPJswcyYL80ECRbToS5r9wYvljBgewzesm98l3d15ELGYr4dsqufqNJ9Cg==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/form@2.1.18':
- resolution: {integrity: sha512-cBlliX6uiIUHDMF/bf5u1JhaA1+ddJHfmDPGfdl25c0mSWbyJqWJ0f1N2KZfrOf8kBkXdWCDXgK5sr3h9n22xg==}
+ '@heroui/form@2.1.24':
+ resolution: {integrity: sha512-zA6eeRXz8DS0kb8VMsiuRQOs4mtVmKgalNZ91xJSqD68CmdE4WI5Ig3rxB9jdl/fd1VVkO853GPp5mzizmNjvA==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18'
react-dom: '>=18'
- '@heroui/framer-utils@2.1.15':
- resolution: {integrity: sha512-SH6hIz0OrhJrx284Gnp1EpCnNL8Dkt3XFmtHogNsE9ggRwMLy1xKIqyVni0V4ZmUe1DNGKAW9ywHV3onp3pFfg==}
- peerDependencies:
- framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
- react: '>=18 || >=19.0.0-rc.0'
- react-dom: '>=18 || >=19.0.0-rc.0'
-
'@heroui/framer-utils@2.1.20':
resolution: {integrity: sha512-DigZrwJp3+ay7rnjIW4ZGXen4QmxDgdvg6xvBK5T6H3JLN6NN+F7kknjK+kFh7tOb1NzuanguribvsufGqMe4w==}
peerDependencies:
@@ -1315,253 +1311,224 @@ packages:
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/image@2.2.12':
- resolution: {integrity: sha512-WJmdp86ibq0XJzi64a/n/c5xEDHNvBD5VU7hinyasRLQBa159Hw4Mab7sueFVBX6ELWj/MIyRb9GK8wz9n3Pwg==}
+ '@heroui/image@2.2.15':
+ resolution: {integrity: sha512-7/DIVZJh2CIZuzoRW9/XVLRyLTWsqNFQgEknEAjGudAUxlcu1dJ8ZuFBVC55SfPIrXE7WuGoiG1Q0B1iwW65IA==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/input-otp@2.1.18':
- resolution: {integrity: sha512-JMqQf4j0tx+OkDyN69KKMIHbxsFvbF5ov5WkwDP1h77eD0Wr89FzJz7nUMIpruEwrFtuCT/QnmQuHcBEIwC0sA==}
+ '@heroui/input-otp@2.1.24':
+ resolution: {integrity: sha512-t8zT8mRt/pLR4u1Qw/eyVLCSSvgYehVVXbPor++SVtWAtNMpKp5GuY3CmKsxujZ2BJU8f2itVgHo0UryEXKdRg==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.13'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18'
react-dom: '>=18'
- '@heroui/input@2.4.19':
- resolution: {integrity: sha512-hKkdMNYHoHpwW/wxdbcWW6M9lLzSTQkSC1FwSfmx3Ug399bX9aLbwNj6R7oOpqqilZjbdnVOWDTzQ9B1vu1Sqg==}
+ '@heroui/input@2.4.25':
+ resolution: {integrity: sha512-k5qYabB2wBmRQvrbGb9gk/KjK97H11rzQyvGsJXdoRbRMxoDB2sczpG08IqY1ecHXQT5bHqJ3Qgh6q1ZN+MYxg==}
peerDependencies:
- '@heroui/system': '>=2.4.10'
- '@heroui/theme': '>=2.4.12'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.19'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/kbd@2.2.15':
- resolution: {integrity: sha512-cx/PIi+3Hb3EKF3OdejClgOFXLWiUFM7iLZ4rmbFzY9PJiIkPUQCLLhljjCpJmcbRfYHY/UXwUszsIhm/aoSvA==}
+ '@heroui/kbd@2.2.19':
+ resolution: {integrity: sha512-PP8fMPRVMGqJU3T5ufyjPUrguBxNstdBLIqiwk4G6TXBTrTkfMxTYVNG+gvsB6tjzmVjPsHpv2IvCjG4arLojw==}
peerDependencies:
- '@heroui/theme': '>=2.4.6'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/link@2.2.16':
- resolution: {integrity: sha512-k/F4bQptv0HAWu9MbePpIa8XvPPDXYxw603HlyFK7qqeGM9daXK3ZgEhE/sd2cnatxa9pYuaiimh7ZxMEsCvtQ==}
+ '@heroui/link@2.2.21':
+ resolution: {integrity: sha512-s2jUESfwx+dYvKjM/ct1XAl/hJcEdSykmOt/X9L5YSaGqhhaFzk1QvlUcz0Byu+WAN0OjxRZxAEbEV642IjNDw==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/listbox@2.3.18':
- resolution: {integrity: sha512-CQRp6Lsyq5iqSSTitFmwoBjWff8nEyqLW17yA3UDZNQfUX2g8F/tPfFmDiRQzKykpQTOZ1MhT0SietQHfyv8Eg==}
+ '@heroui/listbox@2.3.23':
+ resolution: {integrity: sha512-8lZupiqN6J7mNR9gbpz8kDRIdInUXrXc+anInxSDGbL7z+PYgnJ+dqice2yJyRZy/8eT5ZpTdfdV/aw9DluNyA==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/menu@2.2.18':
- resolution: {integrity: sha512-O1i1yuiv34jW8nv8rHGIfwXC+1V6ZxTUu3nblR/TjgB8qClf4WV1LtmkDPweQ5rcR3w8+LKGTGMXh/4tfxDD8A==}
+ '@heroui/menu@2.2.23':
+ resolution: {integrity: sha512-Q2X+7dGxiHmTDnlboOi757biHkbci4zpukMDIi7i2UzHdw1SraH/A2K7bUdGMP+7+KxwSDmj19e0/ZHV/TWtaQ==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/modal@2.2.16':
- resolution: {integrity: sha512-H4Apuvs6ohZTweRe2atRtJQp1nI9HSZVMKRgdn8kIqYBP4rZBu3dTPvnqRKzI4cpdQrsAr4J3xJ36Yt/sn0Rpw==}
+ '@heroui/modal@2.2.21':
+ resolution: {integrity: sha512-VZDwDS+UnYrpCYvqkGTIlm9ADy7s8vvQo1ueLts7WCSYpMxWu6YDnJpkHnth2AyhEzdXGIskbMm96TZW5jwdAQ==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/navbar@2.2.17':
- resolution: {integrity: sha512-+8iH0arqTSAs64Pnx8yI5nrfpK/kmkD7vR+WlfEy9rwJ1cuWjesvOttadfG2TnoQO3FJ+Wm4GEvwgmgeXMmpnQ==}
+ '@heroui/navbar@2.2.22':
+ resolution: {integrity: sha512-EMeg18Y3RWQBf0EfSi9pYfCzMva60d0bD1JgZE6IkSjrHJp+iOu9d9y32MlSsUX0sUvjeowYuYeVwg80d9vJqA==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/number-input@2.0.9':
- resolution: {integrity: sha512-UKmr8V6gNjdFDFgdhvU9fVWrChwXdNkg3H2Jh1NiBAjvnAOiZZ8rJsSRxR8gR4bM81Hdo+V6NKATlMYcOWSXZA==}
+ '@heroui/number-input@2.0.15':
+ resolution: {integrity: sha512-GSyHAxbVVfdrmcHzNoJlS4+rWTlRPugT0yHDDI8Yg+JjJ05PTPxEVeNrKnx7dwu3bs2yEreDhBDd5wt/IUZ0kQ==}
peerDependencies:
- '@heroui/system': '>=2.4.10'
- '@heroui/theme': '>=2.4.9'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.19'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/pagination@2.2.17':
- resolution: {integrity: sha512-UL1MRw2zNsvc5gTe9m3ZN12Fiq5NlDKvpXus0EL471QnsZSOc6SsmjVHrLTWs+AmWiEfiQ2ICKjrlR/JYF+ZGQ==}
+ '@heroui/pagination@2.2.22':
+ resolution: {integrity: sha512-HKv4bBSIh+AFkr+mLOL+Qhdt6blL0AtMrAY/WXXTr7yMOKKZsGDBuTgANTgp2yw8z52gX9hm0xs0kZs/73noHA==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/popover@2.3.19':
- resolution: {integrity: sha512-I6IkBea61BKyvJ3NVBSvXMb4HgQwXXBmtag6L+AsGakJ5X+10v5oAuFHYEhhnZ9Uwh3ckqw0dMzQzzh5P4VE6A==}
+ '@heroui/popover@2.3.24':
+ resolution: {integrity: sha512-ZIVGgqg2RAeRisMNhtJEfOk+yvitk0t7RzcQxd6Has/XkNPXStWEmpjW9wI5P9/RPj76ix4fS7ZArQefX+VHUg==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/progress@2.2.15':
- resolution: {integrity: sha512-nWZCw4EAuBZ7hrmmgC1bSzhg2wJScQeop4erUIM59UHFUSYhVbW7GG6Q5wBn+lEkEi/Sn3Tm7OOFDlUa7bRdXA==}
+ '@heroui/progress@2.2.20':
+ resolution: {integrity: sha512-TMnMh/TPGDPr2c91tcD5JyWRph74xENLcaV/jIihh9UZpKKLrzoU1rTCjKbqaK7Dz9y5fcgM8vVAZmf7SK3mWA==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/radio@2.3.18':
- resolution: {integrity: sha512-QCyEFa6eBhkqouf+h4Tk5Xnm6kn8slEwD5c8ol/Se2P/iDWxnXhy4mKiHZq6qhPIgxYqnY4cwNeaR/iz+42XXw==}
+ '@heroui/radio@2.3.24':
+ resolution: {integrity: sha512-IQ1cwsIAff1JvlpqK5El/b2z6JTDqWK8XiTkElvEy4QkY29uIINkYy6kXqbKyZx14pKN0ILou6Z/iR8QUq304g==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.3'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/react-rsc-utils@2.1.7':
- resolution: {integrity: sha512-NYKKOLs+KHA8v0+PxkkhVXxTD0WNvC4QMlMjUVshzpWhjnOHIrtXjAtqO6XezWmiKNKY76FAjnMZP+Be5+j5uw==}
- peerDependencies:
- react: '>=18 || >=19.0.0-rc.0'
-
'@heroui/react-rsc-utils@2.1.9':
resolution: {integrity: sha512-e77OEjNCmQxE9/pnLDDb93qWkX58/CcgIqdNAczT/zUP+a48NxGq2A2WRimvc1uviwaNL2StriE2DmyZPyYW7Q==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/react-utils@2.1.10':
- resolution: {integrity: sha512-Wj3BSQnNFrDzDnN44vYEwTScMpdbylbZwO8UxIY02AoQCBD5QW7Wf0r2FVlrsrjPjMOVeogwlVvCBYvZz5hHnQ==}
- peerDependencies:
- react: '>=18 || >=19.0.0-rc.0'
-
'@heroui/react-utils@2.1.12':
resolution: {integrity: sha512-D+EYFMtBuWGrtsw+CklgAHtQfT17wZcjmKIvUMGOjAFFSLHG9NJd7yOrsZGk90OuJVQ3O1Gj3MfchEmUXidxyw==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/react@2.7.8':
- resolution: {integrity: sha512-ywtnEcf64mj5Q6nwjv2atG+Y6BVSlm8G+QZkGKBeQnMZfKi2oBAsNNEMoC9XW4wWp/nB4t5pJPp28oJaTZcofA==}
+ '@heroui/react@2.8.2':
+ resolution: {integrity: sha512-Z0lG7N/jyCxRhh6CWb+WFEjbA6wyutYwAYyDAq5uOsGjRKUpAv5zm6ByNdS1YqrP4k8sp0g5HijXbLThQyR9BQ==}
peerDependencies:
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/ripple@2.2.14':
- resolution: {integrity: sha512-ZwPFoNJgLRwiY1TQc5FJenSsJZrdOYP80VWRcmXn0uvMjiv674Rjviji1QEpONA0gvvSxYnptB/ere1oi15NUg==}
+ '@heroui/ripple@2.2.18':
+ resolution: {integrity: sha512-EAZrF6hLJTBiv1sF6R3Wfj/pAIO2yIdVNT2vzaNEXEInrB/fFJlnxfka4p89JjuPl3tiC9jAfavv+zK9YhyBag==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/scroll-shadow@2.3.13':
- resolution: {integrity: sha512-RfYfVewf6UR4vr4sIPI2NaNoyK5lLgJwdWNGufE1Km7INelXf3BVdVKLW/Qlq/cES+B4TV3gq5Nto8aen3R1Sg==}
+ '@heroui/scroll-shadow@2.3.16':
+ resolution: {integrity: sha512-T1zTUjSOpmefMTacFQJFrgssY2BBUO+ZoGQnCiybY+XSZDiuMDmOEjNxC71VUuaHXOzYvhLwmzJY4ZnaUOTlXw==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/select@2.4.19':
- resolution: {integrity: sha512-lEeDyA9QvcQSblHbrqmHhY1V1LJjMmVa6gQ5hxHRfaFcxhQFmp+ORinSsuRVojITRoQ9bz/hTNX+tnrSqyHr/w==}
+ '@heroui/select@2.4.25':
+ resolution: {integrity: sha512-vJoIcRsuh340jvG0JI3NkkvG7iHfflyuxf3hJ4UFAiz+oXxjL1TASToHsIlSiwYZtv1Ihdy89b8Jjfrpa0n89g==}
peerDependencies:
- '@heroui/system': '>=2.4.10'
- '@heroui/theme': '>=2.4.12'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/shared-icons@2.1.7':
- resolution: {integrity: sha512-uJ8MKVR6tWWhFqTjyzeuJabLVMvwENX2aCWLAAPcJedKcPEEmxgE8y3CbY7vRRPEJENXOoeAgmcVWdVgPYeRIw==}
+ '@heroui/shared-icons@2.1.10':
+ resolution: {integrity: sha512-ePo60GjEpM0SEyZBGOeySsLueNDCqLsVL79Fq+5BphzlrBAcaKY7kUp74964ImtkXvknTxAWzuuTr3kCRqj6jg==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
'@heroui/shared-utils@2.1.10':
resolution: {integrity: sha512-w6pSRZZBNDG5/aFueSDUWqOIzqUjKojukg7FxTnVeUX+vIlnYV2Wfv+W+C4l+OV7o0t8emeoe5tXZh8QcLEZEQ==}
- '@heroui/shared-utils@2.1.7':
- resolution: {integrity: sha512-1nx7y41P+Bsca7nDC+QFajAoFhSRGvjKhdFeopMQNTvU95L42PD7B0ThjcOretvQD0Ye2TsAEQInwsSgZ6kK/g==}
-
- '@heroui/shared-utils@2.1.9':
- resolution: {integrity: sha512-mM/Ep914cYMbw3T/b6+6loYhuNfzDaph76mzw/oIS05gw1Dhp9luCziSiIhqDGgzYck2d74oWTZlahyCsxf47w==}
-
- '@heroui/skeleton@2.2.12':
- resolution: {integrity: sha512-HlRKMVLgMAfe9wX7BPhTN84Xu+SdJWCtmxLzBWUZVNpLZdjnu2lLOcbkzwo+84tSjsxbLP4tqBW8hdJnxTQVVA==}
+ '@heroui/skeleton@2.2.15':
+ resolution: {integrity: sha512-Y0nRETaOuF5a1VQy6jPczEM4+MQ9dIJVUSDv2WwJeFBnSs47aNKjOj0ooHaECreynOcKcSqC6hdzKCnN2upKrw==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/slider@2.4.16':
- resolution: {integrity: sha512-KbPtHoOcVYZRXWG+LZgZe8mMO067F9eOiYcrKs5sO5nkEx0MgRlM5VeagC32R86P/fT+hHdL8fUGmatRDZ267Q==}
+ '@heroui/slider@2.4.21':
+ resolution: {integrity: sha512-vinWQq8h5f5V5kiuyNmSAIiPbByj8NQz2n6saYxP3R1++n2ywGE/dDWofZV10mfR9XiC8fLtdTxAs/u717E7Mw==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.19'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/snippet@2.2.20':
- resolution: {integrity: sha512-/vSPkL8V6aQK/i0Ipr8bIBZifTF0g0Kq7DAq0QPfKZNqVWE0rhZyndvn1XU+KevGHybN9WDh6LsYqglxlDIm/A==}
+ '@heroui/snippet@2.2.25':
+ resolution: {integrity: sha512-o1qSv6Vlzm4MDxlGcWBovNqDDmbIv50tFgdWtqLbo2rXfO6OuqLxP2IBKC0fyT8r7zXB3lYrG+3BP7Ok/5zcbw==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/spacer@2.2.14':
- resolution: {integrity: sha512-wiksYhtYH+RIhoMJPdQtWFltw9TF5QKqOujecNmRUORlOsPGAPEHUnzVTV8D7qpk4nJaDB/BNdlN40NaPvWEjg==}
+ '@heroui/spacer@2.2.18':
+ resolution: {integrity: sha512-EHUIyWt2w0viR7oSqhbZPP4fHuILOdcq7ejAhid7rqhsJSjfixQQ/V4OY7D8vpzi7KmlyrkfpkjAZqAApiEbuA==}
peerDependencies:
- '@heroui/theme': '>=2.4.6'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/spinner@2.2.16':
- resolution: {integrity: sha512-yC6OWWiDuXK+NiGpUcAnrmDyBwvWHYw5nzVkUPZ+3TpDpVg9pM7xKSSgf7Xk2C1jgI2diAXbEnCRMVJ87s/zfQ==}
+ '@heroui/spinner@2.2.21':
+ resolution: {integrity: sha512-8rBUwVcVESlHfguRXkgC4p7UEymAAUL/E+nOCfqOHqr308bKhVrS2lSjfeRMBGEJqWLf3m5AMhRfwpRbcSVHWg==}
peerDependencies:
- '@heroui/theme': '>=2.4.6'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/switch@2.2.17':
- resolution: {integrity: sha512-32JfQpT39WDkcWDAHvxhrQ0hXSjLEBEZSWvbRZKrdmB9SPGq6F8fs+wAA5OINoa+MJEBZVHjLcNoRFl5uXQtog==}
+ '@heroui/switch@2.2.22':
+ resolution: {integrity: sha512-EwWEKCzHqZT7oj8iYudDdVsZtoCZRCTGQyS5PutETUXvgOAj3fXFWegrLAPPaIeZggguvS3nIVjgaKUnPS2/Fw==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.3'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/system-rsc@2.3.13':
- resolution: {integrity: sha512-zLBrDKCoM4o039t3JdfYZAOlHmn4RzI6gxU+Tw8XJIfvUzpGSvR2seY2XJBbKOonmTpILlnw16ZvHF+KG+nN0w==}
- peerDependencies:
- '@heroui/theme': '>=2.4.6'
- react: '>=18 || >=19.0.0-rc.0'
-
'@heroui/system-rsc@2.3.17':
resolution: {integrity: sha512-XtQJpLN8HkLYJsvfyBWA/RE8w3PJzEjItwGZ0NACCKRiwkQL205WXJNlkzXsO2/+Y7fEKXkqTMNpQYEhnUlEpw==}
peerDependencies:
'@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/system@2.4.15':
- resolution: {integrity: sha512-+QUHscs2RTk5yOFEQXNlQa478P7PTD02ZGP/RTNCviR4E9ZTUifdjfsKA7D4L79S7L8Mkvbz5E2Ruz2ZF0R/IA==}
- peerDependencies:
- framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
- react: '>=18 || >=19.0.0-rc.0'
- react-dom: '>=18 || >=19.0.0-rc.0'
-
'@heroui/system@2.4.20':
resolution: {integrity: sha512-bLl86ghOjsk8JLarLfL8wkuiNySJS1PHtd0mpGbAjVRQZYp4wH27R7hYBV55dre8Zw+nIRq58PgILdos7F+e0w==}
peerDependencies:
@@ -1569,135 +1536,126 @@ packages:
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/table@2.2.18':
- resolution: {integrity: sha512-4KmYMUq77bc6kY4zr5AZoFm4xzML8zAA505q3kUwlKcpiSbbYxebRUJtbf/UE3FY2NlXAiIuUiL7cvKPmOuVnw==}
+ '@heroui/table@2.2.24':
+ resolution: {integrity: sha512-R3jsgmqGqVAI5rxy0MbcL2lOZwJSbaHSDBEPtDj1UCrPlQC7O+VhKMC9D3I0MaX+bCVDfm0wMYmu5mNjmXGXnQ==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/tabs@2.2.16':
- resolution: {integrity: sha512-TlbgjuF+5SI11p1NlbFuvZ6EkNNHJY2UWRR5UV1EOZawllgpg+mP0BMDID8/r7p/1VcV6abAi+3/0kQRRArh8A==}
+ '@heroui/tabs@2.2.21':
+ resolution: {integrity: sha512-vZAmK7d5i9FE9n78jgJWI6jSHofam4CQSD6ejoefuSWPQZ1nJSgkZrMkTKQuXlvjK+zYy5yvkdj1B8PKq1XaIA==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/theme@2.4.12':
- resolution: {integrity: sha512-sm4DOBhJW88U9h0dfXwX3eA6w125jUi/OfFZtV1zUIyXBPF3c1Va23XO6XmGxDTCgBT4iBwpGBoyHbSYpAnaVg==}
- peerDependencies:
- tailwindcss: '>=3.4.0'
-
- '@heroui/theme@2.4.15':
- resolution: {integrity: sha512-cP1N9Rqj5wzsKLpEzNdJQRjX2g9AuCZbRNaIuIGnztqmmGtP3Yykt1RzeQ4ukCdSDjk/PmV8XneTu8OC8Cs8HA==}
+ '@heroui/theme@2.4.20':
+ resolution: {integrity: sha512-wJdsz7XS9M7xbNd0d1EaaK5dCZIEOSI7eCr5A6f5aM48mtqLaXfsj3gYsfCy7GkQAvtKWuicwKe5D94Xoma6GA==}
peerDependencies:
- tailwindcss: '>=3.4.0'
+ tailwindcss: '>=4.0.0'
- '@heroui/toast@2.0.9':
- resolution: {integrity: sha512-V/x7bkRRS5BabF3Oe4sJWiKygkGtN9/mwFw0phJwx7PYV2Q6WuOvOvq+Zbt8bEz21j58glg4u+eLFBChNPYn7A==}
+ '@heroui/toast@2.0.14':
+ resolution: {integrity: sha512-rYOIl+Nj9EfpBEbZ0fpRiZvKYMQrOntscvIQhQgxvCr3j/5AydKbkA2s+yncHxLj/eDoYaaCCZncbj/Q72ndkA==}
peerDependencies:
- '@heroui/system': '>=2.4.10'
- '@heroui/theme': '>=2.4.12'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/tooltip@2.2.16':
- resolution: {integrity: sha512-pdQZTW04P+Ol6fr6ZfCHDVT+BRksx0n2kGJskMpEYKS0Q4Dk1AKmbVxfHYrT7yOQFQTTmTFJzkbbFMLFgg/Wrg==}
+ '@heroui/tooltip@2.2.21':
+ resolution: {integrity: sha512-ob3XeFir06zeeV6Lq6yCmagSNzwMpEQfsNXP0hisPNamCrJXH2OmrGU01nOmBBMLusBmhQ43Cc3OPDCAyKxUfA==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
framer-motion: '>=11.5.6 || >=12.0.0-alpha.1'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-aria-accordion@2.2.11':
- resolution: {integrity: sha512-E3FSS0QdppE7rnlkhvZD2LZDtfqbhkblFC+kMnqcaYsM1fhbdygtyZWrCDdxGku+g37fXxxa3dbPgFBoocTxQw==}
+ '@heroui/use-aria-accordion@2.2.16':
+ resolution: {integrity: sha512-+1YGkxh8dlfHgGfwPc8M1f3hox0dLH6jDxc2cX6HupzZDsIcqerVBo0vppl3t+3DXSyia0BGROa5kuJJOoCUcA==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-aria-button@2.2.13':
- resolution: {integrity: sha512-gYgoaLxF4X8EnKH5HINrujiJlUtyakKRaeUpfohCrCDL/VEHAwi6+wJVC1AvE1gOfFx5db8+2TUw71IaSgUNGA==}
+ '@heroui/use-aria-button@2.2.18':
+ resolution: {integrity: sha512-z2Z2WQSRYG8k23tEzD/+4PueY3Tuk14Ovt74pqW9+zRKffloPEqmj3txGq9Ja5lUQpz22TWR0dtvbxwITJHf6Q==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-aria-link@2.2.14':
- resolution: {integrity: sha512-93IPT2+JKoSMqFbU90zVG0wpjAT40v2MjXIxyV0ziUJZSBaK1KNh1gZlUD9FGl4s6CLIT01reOpkRCp6fBnBvw==}
+ '@heroui/use-aria-link@2.2.19':
+ resolution: {integrity: sha512-833sZSPMq/sBX14MR7yG2xEmGCbeSm/Bx8/TO6usNB37f2xf179xl6GslDMRVxpAjBcgRI9MtP2qBM1ngJbhmw==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-aria-modal-overlay@2.2.12':
- resolution: {integrity: sha512-AWSy2QnX4RHUisH3kFQ708+9YWKa4mZsTzd+Vvh0rpSvgJdU0JW0/15aNj662QtzP4JLn5uLHtqbMbN71ulKzQ==}
+ '@heroui/use-aria-modal-overlay@2.2.17':
+ resolution: {integrity: sha512-exLtnPX31BUJ7Iq6IH7d/Z8MfoCm9GpQ03B332KBLRbHMM+pye3P1h74lNtdQzIf0OHFSMstJ4gLSs4jx3t6KQ==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-aria-multiselect@2.4.12':
- resolution: {integrity: sha512-clGuf5HKOUFM9dj18ZtI0nOsO1md/IHDHaCJyA2I8NgceVNSodK0ZQgR4GRRf4v2y11OzVIYHz6327Xfv4Hvjw==}
+ '@heroui/use-aria-multiselect@2.4.17':
+ resolution: {integrity: sha512-gU6et+auSJV28umz1YJnxjavuMpOvpfym9IhNe59za/Y/mNIwdHJwcEwbL5qc2eK0AFKYuhqMYsv2iaPs4qcMg==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-callback-ref@2.1.6':
- resolution: {integrity: sha512-icFp4WBWTZhypBcyu+5kir7nZLtvtQq7DDvGwkTtxsGnFHgGDc6sXXcOU6AcCdoGefmsiVp5c3D3lZ2pMlGHmA==}
- peerDependencies:
- react: '>=18 || >=19.0.0-rc.0'
-
- '@heroui/use-callback-ref@2.1.7':
- resolution: {integrity: sha512-AKMb+zV8um9y7gnsPgmVPm5WRx0oJc/3XU+banr8qla27+3HhnQZVqk3nlSHIplkseQzMRt3xHj5RPnwKbs71w==}
+ '@heroui/use-aria-overlay@2.0.2':
+ resolution: {integrity: sha512-pujpue203ii/FukApYGfkeTrT1i80t77SUPR7u1er3dkRCUruksvr1AiPQlsUec1UkIpe/jkXpG3Yb+DldsjRg==}
peerDependencies:
- react: '>=18 || >=19.0.0-rc.0'
+ react: '>=18'
+ react-dom: '>=18'
- '@heroui/use-clipboard@2.1.8':
- resolution: {integrity: sha512-itT5PCoMRoa6rjV51Z9wxeDQpSYMZj2sDFYrM7anGFO/4CAsQ/NfQoPwl5+kX0guqCcCGMqgFnNzNyQuNNsPtg==}
+ '@heroui/use-callback-ref@2.1.8':
+ resolution: {integrity: sha512-D1JDo9YyFAprYpLID97xxQvf86NvyWLay30BeVVZT9kWmar6O9MbCRc7ACi7Ngko60beonj6+amTWkTm7QuY/Q==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-data-scroll-overflow@2.2.10':
- resolution: {integrity: sha512-Lza9S7ZWhY3PliahSgDRubrpeT7gnySH67GSTrGQMzYggTDMo2I1Pky7ZaHUnHHYB9Y7WHryB26ayWBOgRtZUQ==}
+ '@heroui/use-clipboard@2.1.9':
+ resolution: {integrity: sha512-lkBq5RpXHiPvk1BXKJG8gMM0f7jRMIGnxAXDjAUzZyXKBuWLoM+XlaUWmZHtmkkjVFMX1L4vzA+vxi9rZbenEQ==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-disclosure@2.2.11':
- resolution: {integrity: sha512-ARZAKoAURaeD+9PlZarlLqQtSx6cUkrO9m6CVRC8lzVKS1jWvT7u+ZfoLF7fS2m1AmONLBPnjREW5oupAluS/w==}
+ '@heroui/use-data-scroll-overflow@2.2.11':
+ resolution: {integrity: sha512-5H7Q31Ub+O7GygbuaNFrItB4VVLGg2wjr4lXD2o414TgfnaSNPNc0Fb6E6A6m0/f6u7fpf98YURoDx+LFkkroA==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-disclosure@2.2.8':
- resolution: {integrity: sha512-GU/cH3si0na6QkWavvR/2LAqsmHQMKZ9Ed/5QsvMBxv5YPXb2fkxaU6KfIR2Jrr4UmQqi9Bi4aFy20eVyYfQUA==}
+ '@heroui/use-disclosure@2.2.15':
+ resolution: {integrity: sha512-a29HObRfjb6pQ7lvv/WZbvXhGv4BLI4fDrEnVnybfFdC3pCmwyoZxOuqraiDT8IXvVFIiuIcX6719ezruo64kQ==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-draggable@2.1.11':
- resolution: {integrity: sha512-Oi0JwC8F3cCfpPY5c6UpEGsC0cJW3vZ8rwyn0RuTKV7DjaU52YARS56KqJk0udli4R1fjtwrTNuye3TJcS+0ww==}
+ '@heroui/use-draggable@2.1.16':
+ resolution: {integrity: sha512-IcpdnMLmcIDeo7EG41VHSE2jBbYP5dEyNThFirReNh8fMZ6rW2hAd0lf0M0/R5kgTSKUxdNhecY6csDedP+8gA==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-image@2.1.9':
- resolution: {integrity: sha512-rHfPv4PkRN6mUG3eoBZBi8P8FnM37Kb/lOUM5M5kWtPMRpdfpgDxGQjf24K2lwSQM5xVG1H8WlF1Wipcd0kpmA==}
+ '@heroui/use-form-reset@2.0.1':
+ resolution: {integrity: sha512-6slKWiLtVfgZnVeHVkM9eXgjwI07u0CUaLt2kQpfKPqTSTGfbHgCYJFduijtThhTdKBhdH6HCmzTcnbVlAxBXw==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-intersection-observer@2.2.11':
- resolution: {integrity: sha512-QcS1H1zVw8keoHSlT7cxmTuCCMk260/1gmpMM8zVAs0nF8tVL8xylsI1chHSIxZvsL1SNOPC4J++eUeG8QHEEQ==}
+ '@heroui/use-image@2.1.11':
+ resolution: {integrity: sha512-zG3MsPvTSqW69hSDIxHsNJPJfkLoZA54x0AkwOTiqiFh5Z+3ZaQvMTn31vbuMIKmHRpHkkZOTc85cqpAB1Ct4w==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-is-mobile@2.2.9':
- resolution: {integrity: sha512-UVc9wKK3kg2bIAQPaKuCA53qd1Snrd8yxIf/dtbh3PqYjqoyN7c1hUFZxe9ZW8Vb3AovquWDnPYbx4vjdzcQiQ==}
+ '@heroui/use-intersection-observer@2.2.14':
+ resolution: {integrity: sha512-qYJeMk4cTsF+xIckRctazCgWQ4BVOpJu+bhhkB1NrN+MItx19Lcb7ksOqMdN5AiSf85HzDcAEPIQ9w9RBlt5sg==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-is-mounted@2.1.7':
- resolution: {integrity: sha512-Msf4eWWUEDofPmvaFfS4azftO9rIuKyiagxsYE73PSMcdB+7+PJSMTY5ZTM3cf/lwUJzy1FQvyTiCKx0RQ5neA==}
+ '@heroui/use-is-mobile@2.2.12':
+ resolution: {integrity: sha512-2UKa4v1xbvFwerWKoMTrg4q9ZfP9MVIVfCl1a7JuKQlXq3jcyV6z1as5bZ41pCsTOT+wUVOFnlr6rzzQwT9ZOA==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-measure@2.1.7':
- resolution: {integrity: sha512-H586tr/bOH08MAufeiT35E1QmF8SPQy5Ghmat1Bb+vh/6KZ5S0K0o95BE2to7sXE9UCJWa7nDFuizXAGbveSiA==}
+ '@heroui/use-is-mounted@2.1.8':
+ resolution: {integrity: sha512-DO/Th1vD4Uy8KGhd17oGlNA4wtdg91dzga+VMpmt94gSZe1WjsangFwoUBxF2uhlzwensCX9voye3kerP/lskg==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
@@ -1706,36 +1664,36 @@ packages:
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-pagination@2.2.12':
- resolution: {integrity: sha512-tbVad95Z4ECbfagZMU2bg4ofMdHAmA7gA3qtUXPvwDcUZqCxvVm+5RiGUPF0wVHWTRTguntJO5vmGQBInUbeuw==}
+ '@heroui/use-pagination@2.2.16':
+ resolution: {integrity: sha512-EF0MyFRBglTPhcxBlyt+omdgBjLn7mKzQOJuNs1KaBQJBEoe+XPV0eVBleXu32UTz5Q89SsMYGMNbOgpxeU8SA==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-safe-layout-effect@2.1.6':
- resolution: {integrity: sha512-yLT6zrlcZGJX4KKenzvR6lPS42Lf/Q0Q8ErpufLSkTdX4uk/ThGB/CRwdXfP+TPFLIfjXdsgCHgZr2ZAQJaG5Q==}
+ '@heroui/use-resize@2.1.8':
+ resolution: {integrity: sha512-htF3DND5GmrSiMGnzRbISeKcH+BqhQ/NcsP9sBTIl7ewvFaWiDhEDiUHdJxflmJGd/c5qZq2nYQM/uluaqIkKA==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-safe-layout-effect@2.1.7':
- resolution: {integrity: sha512-ZiMc+nVjcE5aArC4PEmnLHSJj0WgAXq3udr7FZaosP/jrRdn5VPcfF9z9cIGNJD6MkZp+YP0XGslrIFKZww0Hw==}
+ '@heroui/use-safe-layout-effect@2.1.8':
+ resolution: {integrity: sha512-wbnZxVWCYqk10XRMu0veSOiVsEnLcmGUmJiapqgaz0fF8XcpSScmqjTSoWjHIEWaHjQZ6xr+oscD761D6QJN+Q==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-scroll-position@2.1.7':
- resolution: {integrity: sha512-c91Elycrq51nhpWqFIEBy04P+KBJjnEz4u1+1c7txnjs/k0FOD5EBD8+Jf8GJbh4WYp5N936XFvCcE7gB1C9JQ==}
+ '@heroui/use-scroll-position@2.1.8':
+ resolution: {integrity: sha512-NxanHKObxVfWaPpNRyBR8v7RfokxrzcHyTyQfbgQgAGYGHTMaOGkJGqF8kBzInc3zJi+F0zbX7Nb0QjUgsLNUQ==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/use-update-effect@2.1.7':
- resolution: {integrity: sha512-G7Crf4vdJh2bwyQQ5+dN+IfvtHpRNkNlEXVDE87Kb15fJ7Rnokt3webnogBreZ9l7SbHpEGvx5sZPsgUHgrTMg==}
+ '@heroui/use-viewport-size@2.0.1':
+ resolution: {integrity: sha512-blv8BEB/QdLePLWODPRzRS2eELJ2eyHbdOIADbL0KcfLzOUEg9EiuVk90hcSUDAFqYiJ3YZ5Z0up8sdPcR8Y7g==}
peerDependencies:
react: '>=18 || >=19.0.0-rc.0'
- '@heroui/user@2.2.15':
- resolution: {integrity: sha512-0v9IYY+NEct3RN7yAoAx75baX2Tmww7oa6qcMrEgI6y0/8OKXwDwqSc1Cb8VAAwTotpWv46Ek09JNwAx+uJLNA==}
+ '@heroui/user@2.2.20':
+ resolution: {integrity: sha512-KnqFtiZR18nlpSEJzA6/aGhNMnuWjQx6L7JbF8kAA2CdhHEBABRIsqKN1qBRon7awMilzBOvlHe6yuk1sEqJHg==}
peerDependencies:
- '@heroui/system': '>=2.4.7'
- '@heroui/theme': '>=2.4.6'
+ '@heroui/system': '>=2.4.18'
+ '@heroui/theme': '>=2.4.17'
react: '>=18 || >=19.0.0-rc.0'
react-dom: '>=18 || >=19.0.0-rc.0'
@@ -1925,10 +1883,17 @@ packages:
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
+ '@isaacs/fs-minipass@4.0.1':
+ resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
+ engines: {node: '>=18.0.0'}
+
'@jridgewell/gen-mapping@0.3.8':
resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
engines: {node: '>=6.0.0'}
+ '@jridgewell/remapping@2.3.5':
+ resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
'@jridgewell/resolve-uri@3.1.2':
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
engines: {node: '>=6.0.0'}
@@ -2480,50 +2445,44 @@ packages:
'@radix-ui/rect@1.1.1':
resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==}
- '@react-aria/breadcrumbs@3.5.23':
- resolution: {integrity: sha512-4uLxuAgPfXds8sBc/Cg0ml7LKWzK+YTwHL7xclhQUkPO32rzlHDl+BJ5cyWhvZgGUf8JJXbXhD5VlJJzbbl8Xg==}
- 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
-
- '@react-aria/button@3.13.0':
- resolution: {integrity: sha512-BEcTQb7Q8ZrAtn0scPDv/ErZoGC1FI0sLk0UTPGskuh/RV9ZZGFbuSWTqOwV8w5CS6VMvPjH6vaE8hS7sb5DIw==}
+ '@react-aria/breadcrumbs@3.5.27':
+ resolution: {integrity: sha512-fuXD9nvBaBVZO0Z6EntBlxQD621/2Ldcxz76jFjc4V/jNOq/6BIVQRtpnAYYrSTiW3ZV2IoAyxRWNxQU22hOow==}
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
- '@react-aria/calendar@3.8.0':
- resolution: {integrity: sha512-9vms/fWjJPZkJcMxciwWWOjGy/Q0nqI6FV0pYbMZbqepkzglEaVd98kl506r/4hLhWKwLdTfqCgbntRecj8jBg==}
+ '@react-aria/button@3.14.0':
+ resolution: {integrity: sha512-we6z+2GpZO8lGD6EPmYH2S87kLCpU14D2E3tD2vES+SS2sZM2qcm2dUGpeo4+gZqBToLWKEBAGCSlkWEtgS19A==}
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
- '@react-aria/checkbox@3.15.4':
- resolution: {integrity: sha512-ZkDJFs2EfMBXVIpBSo4ouB+NXyr2LRgZNp2x8/v+7n3aTmMU8j2PzT+Ra2geTQbC0glMP7UrSg4qZblqrxEBcQ==}
+ '@react-aria/calendar@3.9.0':
+ resolution: {integrity: sha512-YxHLqL/LZrgwYGKzlQ96Fgt6gC+Q1L8k56sD51jJAtiD+YtT/pKJfK1zjZ3rtHtPTDYzosJ8vFgOmZNpnKQpXQ==}
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
- '@react-aria/combobox@3.12.2':
- resolution: {integrity: sha512-EgddiF8VnAjB4EynJERPn4IoDMUabI8GiKOQZ6Ar3MlRWxQnUfxPpZwXs8qWR3dPCzYUt2PhBinhBMjyR1yRIw==}
+ '@react-aria/checkbox@3.16.0':
+ resolution: {integrity: sha512-XPaMz1/iVBG6EbJOPYlNtvr+q4f0axJeoIvyzWW3ciIdDSX/3jYuFg/sv/b3OQQl389cbQ/WUBQyWre/uXWVEg==}
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
- '@react-aria/datepicker@3.14.2':
- resolution: {integrity: sha512-O7fdzcqIJ7i/+8SGYvx4tloTZgK4Ws8OChdbFcd2rZoRPqxM50M6J+Ota8hTet2wIhojUXnM3x2na3EvoucBXA==}
+ '@react-aria/combobox@3.13.0':
+ resolution: {integrity: sha512-eBa8aWcL3Ar/BvgSaqYDmNQP70LPZ7us2myM31QQt2YDRptqGHd44wzXCts9SaDVIeMVy+AEY2NkuxrVE6yNrw==}
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
- '@react-aria/dialog@3.5.24':
- resolution: {integrity: sha512-tw0WH89gVpHMI5KUQhuzRE+IYCc9clRfDvCppuXNueKDrZmrQKbeoU6d0b5WYRsBur2+d7ErtvpLzHVqE1HzfA==}
+ '@react-aria/datepicker@3.15.0':
+ resolution: {integrity: sha512-AONeLj7sMKz4JmzCu4bhsqwcNFXCSWoaBhi4wOJO9+WYmxudn5mSI9ez8NMCVn+s5kcYpyvzrrAFf/DvQ4UDgw==}
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
- '@react-aria/focus@3.20.2':
- resolution: {integrity: sha512-Q3rouk/rzoF/3TuH6FzoAIKrl+kzZi9LHmr8S5EqLAOyP9TXIKG34x2j42dZsAhrw7TbF9gA8tBKwnCNH4ZV+Q==}
+ '@react-aria/dialog@3.5.28':
+ resolution: {integrity: sha512-S9dgdFBQc9LbhyBiHwGPSATwtvsIl6h+UnxDJ4oKBSse+wxdAyshbZv2tyO5RFbe3k73SAgU7yKocfg7YyRM0A==}
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
@@ -2534,14 +2493,14 @@ packages:
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
- '@react-aria/form@3.0.15':
- resolution: {integrity: sha512-kk8AnLz+EOgnn3sTaXYmtw+YzVDc1of/+xAkuOupQi6zQFnNRjc99JlDbKHoUZ39urMl+8lsp/1b9VPPhNrBNw==}
+ '@react-aria/form@3.1.0':
+ resolution: {integrity: sha512-aDAOZafrn0V8e09mDAtCvc+JnpnkFM9X8cbI5+fdXsXAA+JxO+3uRRfnJHBlIL0iLc4C4OVWxBxWToV95pg1KA==}
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
- '@react-aria/grid@3.13.0':
- resolution: {integrity: sha512-RcuJYA4fyJ83MH3SunU+P5BGkx3LJdQ6kxwqwWGIuI9eUKc7uVbqvN9WN3fI+L0QfxqBFmh7ffRxIdQn7puuzw==}
+ '@react-aria/grid@3.14.3':
+ resolution: {integrity: sha512-O4Ius5tJqKcMGfQT6IXD4MnEOeq6f/59nKmfCLTXMREFac/oxafqanUx3zrEVYbaqLOjEmONcd8S61ptQM6aPg==}
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
@@ -2558,65 +2517,47 @@ packages:
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
- '@react-aria/i18n@3.12.8':
- resolution: {integrity: sha512-V/Nau9WuwTwxfFffQL4URyKyY2HhRlu9zmzkF2Hw/j5KmEQemD+9jfaLueG2CJu85lYL06JrZXUdnhZgKnqMkA==}
- 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
-
- '@react-aria/interactions@3.25.0':
- resolution: {integrity: sha512-GgIsDLlO8rDU/nFn6DfsbP9rfnzhm8QFjZkB9K9+r+MTSCn7bMntiWQgMM+5O6BiA8d7C7x4zuN4bZtc0RBdXQ==}
- 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
-
'@react-aria/interactions@3.25.4':
resolution: {integrity: sha512-HBQMxgUPHrW8V63u9uGgBymkMfj6vdWbB0GgUJY49K9mBKMsypcHeWkWM6+bF7kxRO728/IK8bWDV6whDbqjHg==}
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
- '@react-aria/label@3.7.17':
- resolution: {integrity: sha512-Fz7IC2LQT2Y/sAoV+gFEXoULtkznzmK2MmeTv5shTNjeTxzB1BhQbD4wyCypi7eGsnD/9Zy+8viULCsIUbvjWw==}
+ '@react-aria/label@3.7.20':
+ resolution: {integrity: sha512-Hw7OsC2GBnjptyW1lC1+SNoSIZA0eIh02QnNDr1XX2S+BPfn958NxoI7sJIstO/TUpQVNqdjEN/NI6+cyuJE6g==}
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
- '@react-aria/landmark@3.0.2':
- resolution: {integrity: sha512-KVXa9s3fSgo/PiUjdbnPh3a1yS4t2bMZeVBPPzYAgQ4wcU2WjuLkhviw+5GWSWRfT+jpIMV7R/cmyvr0UHvRfg==}
+ '@react-aria/landmark@3.0.5':
+ resolution: {integrity: sha512-klUgRGQyTv5qWFQ0EMMLBOLa87qSTGjWoiMvytL9EgJCACkn/OzNMPbqVSkMADvadDyWCMWFYWvfweLxl3T5yw==}
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
- '@react-aria/link@3.8.0':
- resolution: {integrity: sha512-gpDD6t3FqtFR9QjSIKNpmSR3tS4JG2anVKx2wixuRDHO6Ddexxv4SBzsE1+230p+FlFGjftFa2lEgQ7RNjZrmA==}
+ '@react-aria/link@3.8.4':
+ resolution: {integrity: sha512-7cPRGIo7x6ZZv1dhp2xGjqLR1snazSQgl7tThrBDL5E8f6Yr7SVpxOOK5/EBmfpFkhkmmXEO/Fgo/GPJdc6Vmw==}
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
- '@react-aria/listbox@3.14.3':
- resolution: {integrity: sha512-wzelam1KENUvKjsTq8gfrOW2/iab8SyIaSXfFvGmWW82XlDTlW+oQeA39tvOZktMVGspr+xp8FySY09rtz6UXw==}
+ '@react-aria/listbox@3.14.7':
+ resolution: {integrity: sha512-U5a+AIDblaeQTIA1MDFUaYIKoPwPNAuY7SwkuA5Z7ClDOeQJkiyExmAoKcUXwUkrLULQcbOPKr401q38IL3T7Q==}
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
- '@react-aria/live-announcer@3.4.2':
- resolution: {integrity: sha512-6+yNF9ZrZ4YJ60Oxy2gKI4/xy6WUv1iePDCFJkgpNVuOEYi8W8czff8ctXu/RPB25OJx5v2sCw9VirRogTo2zA==}
-
- '@react-aria/menu@3.18.2':
- resolution: {integrity: sha512-90k+Ke1bhFWhR2zuRI6OwKWQrCpOD99n+9jhG96JZJZlNo5lB+5kS+ufG1LRv5GBnCug0ciLQmPMAfguVsCjEQ==}
- 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
+ '@react-aria/live-announcer@3.4.4':
+ resolution: {integrity: sha512-PTTBIjNRnrdJOIRTDGNifY2d//kA7GUAwRFJNOEwSNG4FW+Bq9awqLiflw0JkpyB0VNIwou6lqKPHZVLsGWOXA==}
- '@react-aria/numberfield@3.11.13':
- resolution: {integrity: sha512-F73BVdIRV8VvKl0omhGaf0E7mdJ7pdPjDP3wYNf410t55BXPxmndItUKpGfxSbl8k6ZYLvQyOqkD6oWSfZXpZw==}
+ '@react-aria/menu@3.19.0':
+ resolution: {integrity: sha512-VLUGbZedKJvK2OFWEpa86GPIaj9QcWox/R9JXmNk6nyrAz/V46OBQENdliV26PEdBZgzrVxGvmkjaH7ZsN/32Q==}
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
- '@react-aria/overlays@3.27.0':
- resolution: {integrity: sha512-2vZVgL7FrloN5Rh8sAhadGADJbuWg69DdSJB3fd2/h5VvcEhnIfNPu9Ma5XmdkApDoTboIEsKZ4QLYwRl98w6w==}
+ '@react-aria/numberfield@3.12.0':
+ resolution: {integrity: sha512-JkgkjYsZ9lN5m3//X3buOKVrA/QJEeeXJ+5T5r6AmF29YdIhD1Plf5AEOWoRpZWQ25chH7FI/Orsf4h3/SLOpg==}
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
@@ -2627,32 +2568,32 @@ packages:
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
- '@react-aria/progress@3.4.22':
- resolution: {integrity: sha512-wK2hath4C9HKgmjCH+iSrAs86sUKqqsYKbEKk9/Rj9rzXqHyaEK9EG0YZDnSjd8kX+N9hYcs5MfJl6AZMH4juQ==}
+ '@react-aria/progress@3.4.25':
+ resolution: {integrity: sha512-KD9Gow+Ip6ZCBdsarR+Hby3c4d99I6L95Ruf7tbCh4ut9i9Dbr+x99OwhpAbT0g549cOyeIqxutPkT+JuzrRuA==}
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
- '@react-aria/radio@3.11.2':
- resolution: {integrity: sha512-6AFJHXMewJBgHNhqkN1qjgwwx6kmagwYD+3Z+hNK1UHTsKe1Uud5/IF7gPFCqlZeKxA+Lvn9gWiqJrQbtD2+wg==}
+ '@react-aria/radio@3.12.0':
+ resolution: {integrity: sha512-//0zZUuHtbm6uZR9+sNRNzVcQpjJKjZj57bDD0lMNj3NZp/Tkw+zXIFy6j1adv3JMe6iYkzEgaB7YRDD1Fe/ZA==}
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
- '@react-aria/selection@3.24.0':
- resolution: {integrity: sha512-RfGXVc04zz41NVIW89/a3quURZ4LT/GJLkiajQK2VjhisidPdrAWkcfjjWJj0n+tm5gPWbi9Rs5R/Rc8mrvq8Q==}
+ '@react-aria/selection@3.25.0':
+ resolution: {integrity: sha512-Q3U0Ya0PTP/TR0a2g+7YEbFVLphiWthmEkHyvOx9HsKSjE8w9wXY3C14DZWKskB/BBrXKJuOWxBDa0xhC83S+A==}
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
- '@react-aria/slider@3.7.18':
- resolution: {integrity: sha512-GBVv5Rpvj/6JH2LnF1zVAhBmxGiuq7R8Ekqyr5kBrCc2ToF3PrTjfGc/mlh0eEtbj+NvAcnlgTx1/qosYt1sGw==}
+ '@react-aria/slider@3.8.0':
+ resolution: {integrity: sha512-D7Sa7q21cV3gBid7frjoYw6924qYqNdJn2oai1BEemHSuwQatRlm1o2j+fnPTy9sYZfNOqXYnv5YjEn0o1T+Gw==}
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
- '@react-aria/spinbutton@3.6.14':
- resolution: {integrity: sha512-oSKe9p0Q/7W39eXRnLxlwJG5dQo4ffosRT3u2AtOcFkk2Zzj+tSQFzHQ4202nrWdzRnQ2KLTgUUNnUvXf0BJcg==}
+ '@react-aria/spinbutton@3.6.17':
+ resolution: {integrity: sha512-gdGc3kkqpvFUd9XsrhPwQHMrG2TY0LVuGGgjvaZwF/ONm9FMz393ogCM0P484HsjU50hClO+yiRRgNjdwDIzPQ==}
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
@@ -2669,62 +2610,50 @@ packages:
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-aria/switch@3.7.2':
- resolution: {integrity: sha512-vaREbp1gFjv+jEMXoXpNK7JYFO/jhwnSYAwEINNWnwf54IGeHvTPaB2NwolYSFvP4HAj8TKYbGFUSz7RKLhLgw==}
- 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
-
- '@react-aria/table@3.17.2':
- resolution: {integrity: sha512-wsF3JqiAKcol1sfeNqTxyzH6+nxu0sAfyuh+XQfp1tvSGx15NifYeNKovNX4EPpUVkAI7jL5Le+eYeYYGELfnw==}
- 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
-
- '@react-aria/tabs@3.10.2':
- resolution: {integrity: sha512-rpEgh//Gnew3le49tQVFOQ6ZyacJdaNUDXHt0ocguXb+2UrKtH54M8oIAE7E8KaB1puQlFXRs+Rjlr1rOlmjEQ==}
+ '@react-aria/switch@3.7.6':
+ resolution: {integrity: sha512-C+Od8hZNZCf3thgtZnZKzHl5b/63Q9xf+Pw6ugLA1qaKazwp46x1EwUVVqVhfAeVhmag++eHs8Lol5ZwQEinjQ==}
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
- '@react-aria/textfield@3.17.2':
- resolution: {integrity: sha512-4KINB0HueYUHUgvi/ThTP27hu4Mv5ujG55pH3dmSRD4Olu/MRy1m/Psq72o8LTf4bTOM9ZP1rKccUg6xfaMidA==}
+ '@react-aria/table@3.17.6':
+ resolution: {integrity: sha512-PSEaeKOIazVEaykeTLudPbDLytJgOPLZJalS/xXY0/KL+Gi0Olchmz4tvS0WBe87ChmlVi6GQqU+stk23aZVWg==}
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
- '@react-aria/toast@3.0.2':
- resolution: {integrity: sha512-iaiHDE1CKYM3BbNEp3A2Ed8YAlpXUGyY6vesKISdHEZ2lJ7r+1hbcFoTNdG8HfbB8Lz5vw8Wd2o+ZmQ2tnDY9Q==}
+ '@react-aria/tabs@3.10.6':
+ resolution: {integrity: sha512-L8MaE7+bu6ByDOUxNPpMMYxdHULhKUfBoXdsSsXqb1z3QxdFW2zovfag0dvpyVWB6ALghX2T0PlTUNqaKA5tGw==}
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
- '@react-aria/toggle@3.11.2':
- resolution: {integrity: sha512-JOg8yYYCjLDnEpuggPo9GyXFaT/B238d3R8i/xQ6KLelpi3fXdJuZlFD6n9NQp3DJbE8Wj+wM5/VFFAi3cISpw==}
+ '@react-aria/textfield@3.18.0':
+ resolution: {integrity: sha512-kCwbyDHi2tRaD/OjagA3m3q2mMZUPeXY7hRqhDxpl2MwyIdd+/PQOJLM8tZr5+m2zvBx+ffOcjZMGTMwMtoV5w==}
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
- '@react-aria/toolbar@3.0.0-beta.15':
- resolution: {integrity: sha512-PNGpNIKIsCW8rxI9XXSADlLrSpikILJKKECyTRw9KwvXDRc44pezvdjGHCNinQcKsQoy5BtkK5cTSAyVqzzTXQ==}
+ '@react-aria/toast@3.0.6':
+ resolution: {integrity: sha512-PoCLWoZzdHIMYY0zIU3WYsHAHPS52sN1gzGRJ+cr5zogU8wwg8lwFZCvs/yql0IhQLsO930zcCXWeL/NsCMrlA==}
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
- '@react-aria/tooltip@3.8.2':
- resolution: {integrity: sha512-ctVTgh1LXvmr1ve3ehAWfvlJR7nHYZeqhl/g1qnA+983LQtc1IF9MraCs92g0m7KpBwCihuA+aYwTPsUHfKfXg==}
+ '@react-aria/toggle@3.12.0':
+ resolution: {integrity: sha512-JfcrF8xUEa2CbbUXp+WQiTBVwSM/dm21v5kueQlksvLfXG6DGE8/zjM6tJFErrFypAasc1JXyrI4dspLOWCfRA==}
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
- '@react-aria/utils@3.28.0':
- resolution: {integrity: sha512-FfpvpADk61OvEnFe37k6jF1zr5gtafIPN9ccJRnPCTqrzuExag01mGi+wX/hWyFK0zAe1OjWf1zFOX3FsFvikg==}
+ '@react-aria/toolbar@3.0.0-beta.19':
+ resolution: {integrity: sha512-G4sgtOUTUUJHznXlpKcY64SxD2gKOqIQXZXjWTVcY/Q5hAjl8gbTt5XIED22GmeIgd/tVl6+lddGj6ESze4vSg==}
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
- '@react-aria/utils@3.28.2':
- resolution: {integrity: sha512-J8CcLbvnQgiBn54eeEvQQbIOfBF3A1QizxMw9P4cl9MkeR03ug7RnjTIdJY/n2p7t59kLeAB3tqiczhcj+Oi5w==}
+ '@react-aria/tooltip@3.8.6':
+ resolution: {integrity: sha512-lW/PegiswGLlCP0CM4FH2kbIrEe4Li2SoklzIRh4nXZtiLIexswoE5/5af7PMtoMAl31or6fHZleVLzZD4VcfA==}
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
@@ -2735,35 +2664,29 @@ packages:
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
- '@react-aria/visually-hidden@3.8.22':
- resolution: {integrity: sha512-EO3R8YTKZ7HkLl9k1Y2uBKYBgpJagth4/4W7mfpJZE24A3fQnCP8zx1sweXiAm0mirR4J6tNaK7Ia8ssP5TpOw==}
- 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
-
'@react-aria/visually-hidden@3.8.26':
resolution: {integrity: sha512-Lz36lTVaQbv5Kn74sPv0l9SnLQ5XHKCoq2zilP14Eb4QixDIqR7Ovj43m+6wi9pynf29jtOb/8D/9jrTjbmmgw==}
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
- '@react-stately/calendar@3.8.0':
- resolution: {integrity: sha512-YAuJiR9EtVThX91gU2ay/6YgPe0LvZWEssu4BS0Atnwk5cAo32gvF5FMta9ztH1LIULdZFaypU/C1mvnayMf+Q==}
+ '@react-stately/calendar@3.8.3':
+ resolution: {integrity: sha512-HTWD6ZKQcXDlvj6glEEG0oi2Tpkaw19y5rK526s04zJs894wFqM9PK0WHthEYqjCeQJ5B/OkyG19XX4lENxnZw==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/checkbox@3.6.13':
- resolution: {integrity: sha512-b8+bkOhobzuJ5bAA16JpYg1tM973eNXD3U4h/8+dckLndKHRjIwPvrL25tzKN7NcQp2LKVCauFesgI+Z+/2FJg==}
+ '@react-stately/checkbox@3.7.0':
+ resolution: {integrity: sha512-opViVhNvxFVHjXhM4nA/E03uvbLazsIKloXX9JtyBCZAQRUag17dpmkekfIkHvP4o7z7AWFoibD8JBFV1IrMcQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/collections@3.12.3':
- resolution: {integrity: sha512-QfSBME2QWDjUw/RmmUjrYl/j1iCYcYCIDsgZda1OeRtt63R11k0aqmmwrDRwCsA+Sv+D5QgkOp4KK+CokTzoVQ==}
+ '@react-stately/collections@3.12.6':
+ resolution: {integrity: sha512-S158RKWGZSodbJXKZDdcnrLzFxzFmyRWDNakQd1nBGhSrW2JV8lDn9ku5Og7TrjoEpkz//B2oId648YT792ilw==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/combobox@3.10.4':
- resolution: {integrity: sha512-sgujLhukIGKskLDrOL4SAbO7WOgLsD7gSdjRQZ0f/e8bWMmUOWEp22T+X1hMMcuVRkRdXlEF1kH2/E6BVanXYw==}
+ '@react-stately/combobox@3.11.0':
+ resolution: {integrity: sha512-W9COXdSOC+uqCZrRHJI0K7emlPb/Tx4A89JHWBcFmiAk+hs1Cnlyjw3aaqEiT8A8/HxDNMO9QcfisWC1iNyE9A==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
@@ -2772,41 +2695,36 @@ packages:
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/datepicker@3.14.0':
- resolution: {integrity: sha512-JSkQfKW0+WpPQyOOeRPBLwXkVfpTUwgZJDnHBCud5kEuQiFFyeAIbL57RNXc4AX2pzY3piQa6OHnjDGTfqClxQ==}
+ '@react-stately/datepicker@3.15.0':
+ resolution: {integrity: sha512-OuBx+h802CoANy6KNR6XuZCndiyRf9vpB32CYZX86nqWy21GSTeT73G41ze5cAH88A/6zmtpYK24nTlk8bdfWA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
'@react-stately/flags@3.1.2':
resolution: {integrity: sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==}
- '@react-stately/form@3.1.3':
- resolution: {integrity: sha512-Jisgm0facSS3sAzHfSgshoCo3LxfO0wmQj98MOBCGXyVL+MSwx2ilb38eXIyBCzHJzJnPRTLaK/E4T49aph47A==}
- peerDependencies:
- react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
-
- '@react-stately/grid@3.11.1':
- resolution: {integrity: sha512-xMk2YsaIKkF8dInRLUFpUXBIqnYt88hehhq2nb65RFgsFFhngE/OkaFudSUzaYPc1KvHpW+oHqvseC+G1iDG2w==}
+ '@react-stately/form@3.2.0':
+ resolution: {integrity: sha512-PfefxvT7/BIhAGpD4oQpdcxnL8cfN0ZTQxQq+Wmb9z3YzK1oM8GFxb8eGdDRG71JeF8WUNMAQVZFhgl00Z/YKg==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/list@3.12.1':
- resolution: {integrity: sha512-N+YCInNZ2OpY0WUNvJWUTyFHtzE5yBtZ9DI4EHJDvm61+jmZ2s3HszOfa7j+7VOKq78VW3m5laqsQNWvMrLFrQ==}
+ '@react-stately/grid@3.11.4':
+ resolution: {integrity: sha512-oaXFSk2eM0PJ0GVniGA0ZlTpAA0AL0O4MQ7V3cHqZAQbwSO0n2pT31GM0bSVnYP/qTF5lQHo3ECmRQCz0fVyMw==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/menu@3.9.3':
- resolution: {integrity: sha512-9x1sTX3Xq2Q3mJUHV+YN9MR36qNzgn8eBSLa40eaFDaOOtoJ+V10m7OriUfpjey7WzLBpq00Sfda54/PbQHZ0g==}
+ '@react-stately/list@3.12.4':
+ resolution: {integrity: sha512-r7vMM//tpmagyNlRzl2NFPPtx+az5R9pM6q7aI4aBf6/zpZt2eX2UW5gaDTGlkQng7r6OGyAgJD52jmGcCJk7Q==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/numberfield@3.9.11':
- resolution: {integrity: sha512-gAFSZIHnZsgIWVPgGRUUpfW6zM7TCV5oS1SCY90ay5nrS7JCXurQbMrWJLOWHTdM5iSeYMgoyt68OK5KD0KHMw==}
+ '@react-stately/menu@3.9.6':
+ resolution: {integrity: sha512-2rVtgeVAiyr7qL8BhmCK/4el49rna/5kADRH5NfPdpXw8ZzaiiHq2RtX443Txj7pUU82CJWQn+CRobq7k6ZTEw==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/overlays@3.6.15':
- resolution: {integrity: sha512-LBaGpXuI+SSd5HSGzyGJA0Gy09V2tl2G/r0lllTYqwt0RDZR6p7IrhdGVXZm6vI0oWEnih7yLC32krkVQrffgQ==}
+ '@react-stately/numberfield@3.10.0':
+ resolution: {integrity: sha512-6C8ML4/e2tcn01BRNfFLxetVaWwz0n0pVROnVpo8p761c6lmTqohqEMNcXCVNw9H0wsa1hug2a1S5PcN2OXgag==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
@@ -2815,63 +2733,53 @@ packages:
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/radio@3.10.12':
- resolution: {integrity: sha512-hFH45CXVa7uyXeTYQy7LGR0SnmGnNRx7XnEXS25w4Ch6BpH8m8SAbhKXqysgcmsE3xrhRas7P9zWw7wI24G28Q==}
- peerDependencies:
- react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
-
- '@react-stately/select@3.6.12':
- resolution: {integrity: sha512-5o/NAaENO/Gxs1yui5BHLItxLnDPSQJ5HDKycuD0/gGC17BboAGEY/F9masiQ5qwRPe3JEc0QfvMRq3yZVNXog==}
- peerDependencies:
- react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
-
- '@react-stately/selection@3.20.1':
- resolution: {integrity: sha512-K9MP6Rfg2yvFoY2Cr+ykA7bP4EBXlGaq5Dqfa1krvcXlEgMbQka5muLHdNXqjzGgcwPmS1dx1NECD15q63NtOw==}
+ '@react-stately/radio@3.11.0':
+ resolution: {integrity: sha512-hsCmKb9e/ygmzBADFYIGpEQ43LrxjWnlKESgxphvlv0Klla4d6XLAYSFOTX1kcjSztpvVWrdl4cIfmKVF1pz2g==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/slider@3.6.3':
- resolution: {integrity: sha512-755X1jhpRD1bqf/5Ax1xuSpZbnG/0EEHGOowH28FLYKy5+1l4QVDGPFYxLB9KzXPdRAr9EF0j2kRhH2d8MCksQ==}
+ '@react-stately/select@3.7.0':
+ resolution: {integrity: sha512-OWLOCKBEj8/XI+vzBSSHQAJu0Hf9Xl/flMhYh47f2b45bO++DRLcVsi8nycPNisudvK6xMQ8a/h4FwjePrCXfg==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/table@3.14.1':
- resolution: {integrity: sha512-7P5h4YBAv3B/7BGq/kln+xSKgJCSq4xjt4HmJA7ZkGnEksUPUokBNQdWwZsy3lX/mwunaaKR9x/YNIu7yXB02g==}
+ '@react-stately/selection@3.20.4':
+ resolution: {integrity: sha512-Hxmc6NtECStYo+Z2uBRhQ80KPhbSF7xXv9eb4qN8dhyuSnsD6c0wc6oAJsv18dldcFz8VrD48aP/uff9mj0hxQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/tabs@3.8.1':
- resolution: {integrity: sha512-1TBbt2BXbemstb/gEYw/NVt3esi5WvgWQW5Z7G8nDzLkpnMHOZXueoUkMxsdm0vhE8p0M9fsJQCMXKvCG3JzJg==}
+ '@react-stately/slider@3.7.0':
+ resolution: {integrity: sha512-quxqkyyxrxLELYEkPrIrucpVPdYDK8yyliv/vvNuHrjuLRIvx6UmssxqESp2EpZfwPYtEB29QXbAKT9+KuXoCQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/toast@3.1.0':
- resolution: {integrity: sha512-9W2+evz+EARrjkR1QPLlOL5lcNpVo6PjMAIygRSaCPJ6ftQAZ6B+7xTFGPFabWh83gwXQDUgoSwC3/vosvxZaQ==}
+ '@react-stately/table@3.14.4':
+ resolution: {integrity: sha512-uhwk8z3DemozD+yHBjSa4WyxKczpDkxhJhW7ZVOY+1jNuTYxc9/JxzPsHICrlDVV8EPWwwyMUz8eO/8rKN7DbA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/toggle@3.8.3':
- resolution: {integrity: sha512-4T2V3P1RK4zEFz4vJjUXUXyB0g4Slm6stE6Ry20fzDWjltuW42cD2lmrd7ccTO/CXFmHLECcXQLD4GEbOj0epA==}
+ '@react-stately/tabs@3.8.4':
+ resolution: {integrity: sha512-2Tr4yXkcNDLyyxrZr+c4FnAW/wkSim3UhDUWoOgTCy3mwlQzdh9r5qJrOZRghn1QvF7p8Ahp7O7qxwd2ZGJrvQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/tooltip@3.5.3':
- resolution: {integrity: sha512-btfy/gQ3Eccudx//4HkyQ+CRr3vxbLs74HYHthaoJ9GZbRj/3XDzfUM2X16zRoqTZVrIz/AkUj7AfGfsitU5nQ==}
+ '@react-stately/toast@3.1.2':
+ resolution: {integrity: sha512-HiInm7bck32khFBHZThTQaAF6e6/qm57F4mYRWdTq8IVeGDzpkbUYibnLxRhk0UZ5ybc6me+nqqPkG/lVmM42Q==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/tree@3.8.9':
- resolution: {integrity: sha512-j/LLI9UvbqcfOdl2v9m3gET3etUxoQzv3XdryNAbSkg0jTx8/13Fgi/Xp98bUcNLfynfeGW5P/fieU71sMkGog==}
+ '@react-stately/toggle@3.9.0':
+ resolution: {integrity: sha512-1URd97R5nbFF9Hc1nQBhvln55EnOkLNz6pjtXU7TCnV4tYVbe+tc++hgr5XRt6KAfmuXxVDujlzRc6QjfCn0cQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/utils@3.10.5':
- resolution: {integrity: sha512-iMQSGcpaecghDIh3mZEpZfoFH3ExBwTtuBEcvZ2XnGzCgQjeYXcMdIUwAfVQLXFTdHUHGF6Gu6/dFrYsCzySBQ==}
+ '@react-stately/tooltip@3.5.6':
+ resolution: {integrity: sha512-BnOtE7726t1sCKPGbwzzEtEx40tjpbJvw5yqpoVnAV0OLfrXtLVYfd7tWRHmZOYmhELaUnY+gm3ZFYtwvnjs+A==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/utils@3.10.6':
- resolution: {integrity: sha512-O76ip4InfTTzAJrg8OaZxKU4vvjMDOpfA/PGNOytiXwBbkct2ZeZwaimJ8Bt9W1bj5VsZ81/o/tW4BacbdDOMA==}
+ '@react-stately/tree@3.9.1':
+ resolution: {integrity: sha512-dyoPIvPK/cs03Tg/MQSODi2kKYW1zaiOG9KC2P0c8b44mywU2ojBKzhSJky3dBkJ4VVGy7L+voBh50ELMjEa8Q==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
@@ -2880,8 +2788,8 @@ packages:
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-stately/virtualizer@4.3.2':
- resolution: {integrity: sha512-KxR0s6IBqUD2TfDM3mAOtiTZLb1zOwcuCeUOvCKNqzEdFhh7nEJPrG33mgJn64S4kM11c0AsPwBlxISqdvCXJg==}
+ '@react-stately/virtualizer@4.4.2':
+ resolution: {integrity: sha512-csU/Bbq1+JYCXlF3wKHa690EhV4/uuK5VwZZvi9jTMqjblDiNUwEmIcx78J8aoadjho5wgRw3ddE9NPDGcVElA==}
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
@@ -2891,13 +2799,8 @@ packages:
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/breadcrumbs@3.7.12':
- resolution: {integrity: sha512-+LvGEADlv11mLQjxEAZriptSYJJTP+2OIFEKx0z9mmpp+8jTlEHFhAnRVaE6I9QCxcDB5F6q/olfizSwOPOMIg==}
- peerDependencies:
- react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
-
- '@react-types/button@3.12.0':
- resolution: {integrity: sha512-YrASNa+RqGQpzJcxNAahzNuTYVID1OE6HCorrEOXIyGS3EGogHsQmFs9OyThXnGHq6q4rLlA806/jWbP9uZdxA==}
+ '@react-types/breadcrumbs@3.7.15':
+ resolution: {integrity: sha512-0RsymrsOAsx443XRDJ1krK+Lusr4t0qqExmzFe7/XYXOn/RbGKjzSdezsoWfTy8Hjks0YbfQPVKnNxg9LKv4XA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
@@ -2906,63 +2809,58 @@ packages:
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/calendar@3.7.0':
- resolution: {integrity: sha512-RiEfX2ZTcvfRktQc5obOJtNTgW+UwjNOUW5yf9CLCNOSM07e0w5jtC1ewsOZZbcctMrMCljjL8niGWiBv1wQ1Q==}
- peerDependencies:
- react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
-
- '@react-types/checkbox@3.9.3':
- resolution: {integrity: sha512-h6wmK7CraKHKE6L13Ut+CtnjRktbMRhkCSorv7eg82M6p4PDhZ7mfDSh13IlGR4sryT8Ka+aOjOU+EvMrKiduA==}
+ '@react-types/calendar@3.7.3':
+ resolution: {integrity: sha512-gofPgVpSawJ0iGO01SbVH46u3gdykHlGT5BfGU1cRnsOR2tJX38dekO/rnuGsMQYF0+kU6U9YVae+XoOFJNnWg==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/combobox@3.13.4':
- resolution: {integrity: sha512-4mX7eZ/Bv3YWzEzLEZAF/TfKM+I+SCsvnm/cHqOJq3jEE8aVU1ql4Q1+3+SvciX3pfFIfeKlu9S3oYKRT5WIgg==}
+ '@react-types/checkbox@3.10.0':
+ resolution: {integrity: sha512-DJ84ilBDvZddE/Sul97Otee4M6psrPRaJm2a1Bc7M3Y5UKo6d6RGXdcDarRRpbnS7BeAbVanKiMS2ygI9QHh9g==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/datepicker@3.12.0':
- resolution: {integrity: sha512-dw/xflOdQPQ3uEABaBrZRTvjsMRu5/VZjRx9ygc64sX2N7HKIt+foMPXKJ+1jhtki2p4gigNVjcnJndJHoj9SA==}
+ '@react-types/combobox@3.13.7':
+ resolution: {integrity: sha512-R7MQ4Qm4fryo6FCg3Vo/l9wxkYVG05trsLbxzMvvxCMkpcoHUPhy8Ll33eXA3YP74Rs/IaM9d0d/amSUZ4M9wg==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/dialog@3.5.17':
- resolution: {integrity: sha512-rKe2WrT272xuCH13euegBGjJAORYXJpHsX2hlu/f02TmMG4nSLss9vKBnY2N7k7nci65k5wDTW6lcsvQ4Co5zQ==}
+ '@react-types/datepicker@3.13.0':
+ resolution: {integrity: sha512-AG/iGcdQ5SVSjw8Ta7bCdGNkMda+e+Z7lOHxDawL44SII8LtZroBDlaCpb178Tvo17bBfJ6TvWXlvSpBY8GPRg==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/form@3.7.11':
- resolution: {integrity: sha512-umqy2Kvg3ooJi+Wqun95tKbKN51gtNt9s7OFLdwCtfWa6GvHFOixSjqAvZbo+m5qC3X/1kMIz3Dg698l0/+oLQ==}
+ '@react-types/dialog@3.5.20':
+ resolution: {integrity: sha512-ebn8jW/xW/nmRATaWIPHVBIpIFWSaqjrAxa58f5TXer5FtCD9pUuzAQDmy/o22ucB0yvn6Kl+fjb3SMbMdALZQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/grid@3.3.1':
- resolution: {integrity: sha512-bPDckheJiHSIzSeSkLqrO6rXRLWvciFJr9rpCjq/+wBj6HsLh2iMpkB/SqmRHTGpPlJvlu0b7AlxK1FYE0QSKA==}
+ '@react-types/form@3.7.14':
+ resolution: {integrity: sha512-P+FXOQR/ISxLfBbCwgttcR1OZGqOknk7Ksgrxf7jpc4PuyUC048Jf+FcG+fARhoUeNEhv6kBXI5fpAB6xqnDhA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/link@3.6.0':
- resolution: {integrity: sha512-BQ5Tktb+fUxvtqksAJZuP8Z/bpmnQ/Y/zgwxfU0OKmIWkKMUsXY+e0GBVxwFxeh39D77stpVxRsTl7NQrjgtSw==}
+ '@react-types/grid@3.3.4':
+ resolution: {integrity: sha512-8XNn7Czhl+D1b2zRwdO8c3oBJmKgevT/viKJB4qBVFOhK0l/p3HYDZUMdeclvUfSt4wx4ASpI7MD3v1vmN54oA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/listbox@3.6.0':
- resolution: {integrity: sha512-+1ugDKTxson/WNOQZO4BfrnQ6cGDt+72mEytXMsSsd4aEC+x3RyUv6NKwdOl4n602cOreo0MHtap1X2BOACVoQ==}
+ '@react-types/link@3.6.3':
+ resolution: {integrity: sha512-XIYEl9ZPa5mLy8uGQabdhPaFVmnvxNSYF59t0vs/IV0yxeoPvrjKjRAbXS+WP9zYMXIkHYNYYucriCkqKhotJA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/menu@3.10.0':
- resolution: {integrity: sha512-DKMqEmUmarVCK0jblNkSlzSH53AAsxWCX9RaKZeP9EnRs2/l1oZRuiQVHlOQRgYwEigAXa2TrwcX4nnxZ+U36Q==}
+ '@react-types/listbox@3.7.2':
+ resolution: {integrity: sha512-MRpBhApR1jJNASoVWsEvH5vf89TJw+l9Lt1ssawop0K2iYF5PmkthRdqcpYcTkFu5+f5QvFchVsNJ3TKD4cf2A==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/numberfield@3.8.10':
- resolution: {integrity: sha512-mdb4lMC4skO8Eqd0GeU4lJgDTEvqIhtINB5WCzLVZFrFVuxgWDoU5otsu0lbWhCnUA7XWQxupGI//TC1LLppjQ==}
+ '@react-types/menu@3.10.3':
+ resolution: {integrity: sha512-Vd3t7fEbIOiq7kBAHaihfYf+/3Fuh0yK2KNjJ70BPtlAhMRMDVG3m0PheSTm3FFfj+uAdQdfc2YKPnMBbWjDuQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/overlays@3.8.14':
- resolution: {integrity: sha512-XJS67KHYhdMvPNHXNGdmc85gE+29QT5TwC58V4kxxHVtQh9fYzEEPzIV8K84XWSz04rRGe3fjDgRNbcqBektWQ==}
+ '@react-types/numberfield@3.8.13':
+ resolution: {integrity: sha512-zRSqInmxOTQJZt2fjAhuQK3Wa1vCOlKsRzUVvxTrE8gtQxlgFxirmobuUnjTEhwkFyb0bq8GvVfQV1E95Si2yw==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
@@ -2971,18 +2869,18 @@ packages:
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/progress@3.5.11':
- resolution: {integrity: sha512-CysuMld/lycOckrnlvrlsVoJysDPeBnUYBChwtqwiv4ZNRXos+wgAL1ows6dl7Nr57/FH5B4v5gf9AHEo7jUvw==}
+ '@react-types/progress@3.5.14':
+ resolution: {integrity: sha512-GeGrjOeHR/p5qQ1gGlN68jb+lL47kuddxMgdR1iEnAlYGY4OtJoEN/EM5W2ZxJRKPcJmzdcY/p/J0PXa8URbSg==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/radio@3.8.8':
- resolution: {integrity: sha512-QfAIp+0CnRSnoRTJVXUEPi+9AvFvRzWLIKEnE9OmgXjuvJCU3QNiwd8NWjNeE+94QBEVvAZQcqGU+44q5poxNg==}
+ '@react-types/radio@3.9.0':
+ resolution: {integrity: sha512-phndlgqMF6/9bOOhO3le00eozNfDU1E7OHWV2cWWhGSMRFuRdf7/d+NjVtavCX75+GJ50MxvXk+KB0fjTuvKyg==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/select@3.9.11':
- resolution: {integrity: sha512-uEpQCgDlrq/5fW05FgNEsqsqpvZVKfHQO9Mp7OTqGtm4UBNAbcQ6hOV7MJwQCS25Lu2luzOYdgqDUN8eAATJVQ==}
+ '@react-types/select@3.10.0':
+ resolution: {integrity: sha512-+xJwYWJoJTCGsaiPAqb6QB79ub1WKIHSmOS9lh/fPUXfUszVs05jhajaN9KjrKmnXds5uh4u6l1JH5J1l2K5pw==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
@@ -3001,33 +2899,33 @@ packages:
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/slider@3.7.10':
- resolution: {integrity: sha512-Yb8wbpu2gS7AwvJUuz0IdZBRi6eIBZq32BSss4UHX0StA8dtR1/K4JeTsArxwiA3P0BA6t0gbR6wzxCvVA9fRw==}
+ '@react-types/slider@3.8.0':
+ resolution: {integrity: sha512-eN6Fd3YCPseGfvfOJDtn9Lh9CrAb8tF3cTAprEcpnGrsxmdW9JQpcuciYuLM871X5D2fYg4WaYMpZaiYssjxBQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/switch@3.5.10':
- resolution: {integrity: sha512-YyNhx4CvuJ0Rvv7yMuQaqQuOIeg+NwLV00NHHJ+K0xEANSLcICLOLPNMOqRIqLSQDz5vDI705UKk8gVcxqPX5g==}
+ '@react-types/switch@3.5.13':
+ resolution: {integrity: sha512-C2EhKBu7g7xhKboPPxhyKtROEti80Ck7TBnKclXt0D4LiwbzpR3qGfuzB+7YFItnhiauP7Uxe+bAfM5ojjtm9w==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/table@3.12.0':
- resolution: {integrity: sha512-dmTzjCYwHf2HBOeTa/CEL177Aox0f0mkeLF5nQw/2z6SBolfmYoAwVTPxTaYFVu4MkEJxQTz9AuAsJvCbRJbhg==}
+ '@react-types/table@3.13.2':
+ resolution: {integrity: sha512-3/BpFIWHXTcGgQEfip87gMNCWPtPNsc3gFkW4qtsevQ+V0577KyNyvQgvFrqMZKnvz3NWFKyshBb7PTevsus4Q==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/tabs@3.3.14':
- resolution: {integrity: sha512-/uKsA7L2dctKU0JEaBWerlX+3BoXpKUFr3kHpRUoH66DSGvAo34vZ7kv/BHMZifJenIbF04GhDBsGp1zjrQKBg==}
+ '@react-types/tabs@3.3.17':
+ resolution: {integrity: sha512-cLcdxWNJe0Kf/pKuPQbEF9Fl+axiP4gB/WVjmAdhCgQ5LCJw2dGcy1LI1SXrlS3PVclbnujD1DJ8z1lIW4Tmww==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/textfield@3.12.1':
- resolution: {integrity: sha512-6YTAMCKjEGuXg0A4bZA77j5QJ1a6yFviMUWsCIL6Dxq5K3TklzVsbAduSbHomPPuvkNTBSW4+TUJrVSnoTjMNA==}
+ '@react-types/textfield@3.12.4':
+ resolution: {integrity: sha512-cOgzI1dT8X1JMNQ9u2UKoV2L28ROkbFEtzY9At0MqTZYYSxYp3Q7i+XRqIBehu8jOMuCtN9ed9EgwVSfkicyLQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
- '@react-types/tooltip@3.4.16':
- resolution: {integrity: sha512-XEyKeqR3YxqJcR0cpigLGEBeRTEzrB0cu++IaADdqXJ8dBzS6s8y9EgR5UvKZmX1CQOBvMfXyYkj7nmJ039fOw==}
+ '@react-types/tooltip@3.4.19':
+ resolution: {integrity: sha512-OR/pwZReWbCIxuHJYB1L4fTwliA+mzVvUJMWwXIRy6Eh5d07spS3FZEKFvOgjMxA1nyv5PLf8eyr5RuuP1GGAA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
@@ -3130,6 +3028,94 @@ packages:
'@tabler/icons@3.33.0':
resolution: {integrity: sha512-NZeFfzcYe7xcBHR3zKoCSrw/cFWvfj6LjenPQ48yVMTGdX854HH9nH44ZfMH8rrDzHBllfjwl4CIX6Vh2tyN0Q==}
+ '@tailwindcss/node@4.1.12':
+ resolution: {integrity: sha512-3hm9brwvQkZFe++SBt+oLjo4OLDtkvlE8q2WalaD/7QWaeM7KEJbAiY/LJZUaCs7Xa8aUu4xy3uoyX4q54UVdQ==}
+
+ '@tailwindcss/oxide-android-arm64@4.1.12':
+ resolution: {integrity: sha512-oNY5pq+1gc4T6QVTsZKwZaGpBb2N1H1fsc1GD4o7yinFySqIuRZ2E4NvGasWc6PhYJwGK2+5YT1f9Tp80zUQZQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [android]
+
+ '@tailwindcss/oxide-darwin-arm64@4.1.12':
+ resolution: {integrity: sha512-cq1qmq2HEtDV9HvZlTtrj671mCdGB93bVY6J29mwCyaMYCP/JaUBXxrQQQm7Qn33AXXASPUb2HFZlWiiHWFytw==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-darwin-x64@4.1.12':
+ resolution: {integrity: sha512-6UCsIeFUcBfpangqlXay9Ffty9XhFH1QuUFn0WV83W8lGdX8cD5/+2ONLluALJD5+yJ7k8mVtwy3zMZmzEfbLg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-freebsd-x64@4.1.12':
+ resolution: {integrity: sha512-JOH/f7j6+nYXIrHobRYCtoArJdMJh5zy5lr0FV0Qu47MID/vqJAY3r/OElPzx1C/wdT1uS7cPq+xdYYelny1ww==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.12':
+ resolution: {integrity: sha512-v4Ghvi9AU1SYgGr3/j38PD8PEe6bRfTnNSUE3YCMIRrrNigCFtHZ2TCm8142X8fcSqHBZBceDx+JlFJEfNg5zQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.1.12':
+ resolution: {integrity: sha512-YP5s1LmetL9UsvVAKusHSyPlzSRqYyRB0f+Kl/xcYQSPLEw/BvGfxzbH+ihUciePDjiXwHh+p+qbSP3SlJw+6g==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.1.12':
+ resolution: {integrity: sha512-V8pAM3s8gsrXcCv6kCHSuwyb/gPsd863iT+v1PGXC4fSL/OJqsKhfK//v8P+w9ThKIoqNbEnsZqNy+WDnwQqCA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.1.12':
+ resolution: {integrity: sha512-xYfqYLjvm2UQ3TZggTGrwxjYaLB62b1Wiysw/YE3Yqbh86sOMoTn0feF98PonP7LtjsWOWcXEbGqDL7zv0uW8Q==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-x64-musl@4.1.12':
+ resolution: {integrity: sha512-ha0pHPamN+fWZY7GCzz5rKunlv9L5R8kdh+YNvP5awe3LtuXb5nRi/H27GeL2U+TdhDOptU7T6Is7mdwh5Ar3A==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@tailwindcss/oxide-wasm32-wasi@4.1.12':
+ resolution: {integrity: sha512-4tSyu3dW+ktzdEpuk6g49KdEangu3eCYoqPhWNsZgUhyegEda3M9rG0/j1GV/JjVVsj+lG7jWAyrTlLzd/WEBg==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+ bundledDependencies:
+ - '@napi-rs/wasm-runtime'
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+ - '@tybys/wasm-util'
+ - '@emnapi/wasi-threads'
+ - tslib
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.1.12':
+ resolution: {integrity: sha512-iGLyD/cVP724+FGtMWslhcFyg4xyYyM+5F4hGvKA7eifPkXHRAUDFaimu53fpNg9X8dfP75pXx/zFt/jlNF+lg==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.1.12':
+ resolution: {integrity: sha512-NKIh5rzw6CpEodv/++r0hGLlfgT/gFN+5WNdZtvh6wpU2BpGNgdjvj6H2oFc8nCM839QM1YOhjpgbAONUb4IxA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@tailwindcss/oxide@4.1.12':
+ resolution: {integrity: sha512-gM5EoKHW/ukmlEtphNwaGx45fGoEmP10v51t9unv55voWh6WrOL19hfuIdo2FjxIaZzw776/BUQg7Pck++cIVw==}
+ engines: {node: '>= 10'}
+
+ '@tailwindcss/postcss@4.1.12':
+ resolution: {integrity: sha512-5PpLYhCAwf9SJEeIsSmCDLgyVfdBhdBpzX1OJ87anT9IVR0Z9pjM0FNixCAUAHGnMBGB8K99SwAheXrT0Kh6QQ==}
+
'@tanstack/react-virtual@3.11.3':
resolution: {integrity: sha512-vCU+OTylXN3hdC8RKg68tPlBPjjxtzon7Ys46MgrSLE+JhSjSTPvoQifV6DQJeJmA8Q3KT6CphJbejupx85vFw==}
peerDependencies:
@@ -3332,9 +3318,6 @@ packages:
'@types/json5@0.0.29':
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
- '@types/lodash.debounce@4.0.9':
- resolution: {integrity: sha512-Ma5JcgTREwpLRwMM+XwBR7DaWe96nC38uCBDFKZWbNKD+osjVzdpnUSwBcqCptrp16sSOLBAUb50Car5I0TCsQ==}
-
'@types/lodash@4.17.16':
resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==}
@@ -3850,20 +3833,10 @@ packages:
resolution: {integrity: sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==}
engines: {node: '>=14'}
- any-promise@1.3.0:
- resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
-
- anymatch@3.1.3:
- resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
- engines: {node: '>= 8'}
-
are-docs-informative@0.0.2:
resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==}
engines: {node: '>=14'}
- arg@5.0.2:
- resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
-
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
@@ -3990,10 +3963,6 @@ packages:
big.js@5.2.2:
resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==}
- binary-extensions@2.3.0:
- resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
- engines: {node: '>=8'}
-
birecord@0.1.1:
resolution: {integrity: sha512-VUpsf/qykW0heRlC8LooCq28Kxn3mAqKohhDG/49rrsQ1dT1CXyj/pgXS+5BSRzFTR/3DyIBOqQOrGyZOh71Aw==}
@@ -4050,10 +4019,6 @@ packages:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'}
- camelcase-css@2.0.1:
- resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
- engines: {node: '>= 6'}
-
caniuse-lite@1.0.30001709:
resolution: {integrity: sha512-NgL3vUTnDrPCZ3zTahp4fsugQ4dc7EKTSzwQDPEel6DMoMnfH2jhry9n2Zm8onbSR+f/QtKHFOA+iAQu4kbtWA==}
@@ -4083,9 +4048,9 @@ packages:
character-reference-invalid@2.0.1:
resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
- chokidar@3.6.0:
- resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
- engines: {node: '>= 8.10.0'}
+ chownr@3.0.0:
+ resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
+ engines: {node: '>=18'}
chrome-trace-event@1.0.4:
resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==}
@@ -4151,10 +4116,6 @@ packages:
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
- commander@4.1.1:
- resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
- engines: {node: '>= 6'}
-
comment-parser@1.4.1:
resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==}
engines: {node: '>= 12.0.0'}
@@ -4343,9 +4304,6 @@ packages:
devlop@1.1.0:
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
- didyoumean@1.2.2:
- resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
-
dir-glob@3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
@@ -4354,9 +4312,6 @@ packages:
resolution: {integrity: sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==}
hasBin: true
- dlv@1.1.3:
- resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
-
doctrine@2.1.0:
resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
engines: {node: '>=0.10.0'}
@@ -4997,8 +4952,8 @@ packages:
fraction.js@4.3.7:
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
- framer-motion@12.5.0:
- resolution: {integrity: sha512-buPlioFbH9/W7rDzYh1C09AuZHAk2D1xTA1BlounJ2Rb9aRg84OXexP0GLd+R83v0khURdMX7b5MKnGTaSg5iA==}
+ framer-motion@12.23.12:
+ resolution: {integrity: sha512-6e78rdVtnBvlEVgu6eFEAgG9v3wLnYEboM8I5O5EXvfKC8gxGQB8wXJdhkMy10iVcn05jl6CNw7/HTsTCfwcWg==}
peerDependencies:
'@emotion/is-prop-valid': '*'
react: ^18.0.0 || ^19.0.0
@@ -5285,10 +5240,6 @@ packages:
resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
engines: {node: '>= 0.4'}
- is-binary-path@2.1.0:
- resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
- engines: {node: '>=8'}
-
is-boolean-object@1.2.2:
resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==}
engines: {node: '>= 0.4'}
@@ -5451,8 +5402,8 @@ packages:
resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
engines: {node: '>= 10.13.0'}
- jiti@1.21.7:
- resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
+ jiti@2.5.1:
+ resolution: {integrity: sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==}
hasBin: true
js-tokens@4.0.0:
@@ -5536,12 +5487,69 @@ packages:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
- lilconfig@3.1.3:
- resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
- engines: {node: '>=14'}
+ lightningcss-darwin-arm64@1.30.1:
+ resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ lightningcss-darwin-x64@1.30.1:
+ resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [darwin]
- lines-and-columns@1.2.4:
- resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+ lightningcss-freebsd-x64@1.30.1:
+ resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ lightningcss-linux-arm-gnueabihf@1.30.1:
+ resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm]
+ os: [linux]
+
+ lightningcss-linux-arm64-gnu@1.30.1:
+ resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ lightningcss-linux-arm64-musl@1.30.1:
+ resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ lightningcss-linux-x64-gnu@1.30.1:
+ resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ lightningcss-linux-x64-musl@1.30.1:
+ resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ lightningcss-win32-arm64-msvc@1.30.1:
+ resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ lightningcss-win32-x64-msvc@1.30.1:
+ resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [win32]
+
+ lightningcss@1.30.1:
+ resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==}
+ engines: {node: '>= 12.0.0'}
loader-runner@4.3.0:
resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==}
@@ -5787,21 +5795,27 @@ packages:
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
engines: {node: '>=16 || 14 >=14.17'}
+ minizlib@3.0.2:
+ resolution: {integrity: sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==}
+ engines: {node: '>= 18'}
+
+ mkdirp@3.0.1:
+ resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==}
+ engines: {node: '>=10'}
+ hasBin: true
+
mlly@1.7.4:
resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==}
- motion-dom@12.5.0:
- resolution: {integrity: sha512-uH2PETDh7m+Hjd1UQQ56yHqwn83SAwNjimNPE/kC+Kds0t4Yh7+29rfo5wezVFpPOv57U4IuWved5d1x0kNhbQ==}
+ motion-dom@12.23.12:
+ resolution: {integrity: sha512-RcR4fvMCTESQBD/uKQe49D5RUeDOokkGRmz4ceaJKDBgHYtZtntC/s2vLvY38gqGaytinij/yi3hMcWVcEF5Kw==}
- motion-utils@12.5.0:
- resolution: {integrity: sha512-+hFFzvimn0sBMP9iPxBa9OtRX35ZQ3py0UHnb8U29VD+d8lQ8zH3dTygJWqK7av2v6yhg7scj9iZuvTS0f4+SA==}
+ motion-utils@12.23.6:
+ resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
- mz@2.7.0:
- resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
-
nanoid@3.3.11:
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -5861,10 +5875,6 @@ packages:
resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==}
engines: {node: ^16.14.0 || >=18.0.0}
- normalize-path@3.0.0:
- resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
- engines: {node: '>=0.10.0'}
-
normalize-range@0.1.2:
resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
engines: {node: '>=0.10.0'}
@@ -5879,10 +5889,6 @@ packages:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
- object-hash@3.0.0:
- resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
- engines: {node: '>= 6'}
-
object-inspect@1.13.4:
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
engines: {node: '>= 0.4'}
@@ -6040,10 +6046,6 @@ packages:
resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==}
engines: {node: '>=0.10.0'}
- pirates@4.0.6:
- resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
- engines: {node: '>= 6'}
-
pkg-dir@4.2.0:
resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
engines: {node: '>=8'}
@@ -6065,36 +6067,6 @@ packages:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
- postcss-import@15.1.0:
- resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
- engines: {node: '>=14.0.0'}
- peerDependencies:
- postcss: ^8.0.0
-
- postcss-js@4.0.1:
- resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
- engines: {node: ^12 || ^14 || >= 16}
- peerDependencies:
- postcss: ^8.4.21
-
- postcss-load-config@4.0.2:
- resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
- engines: {node: '>= 14'}
- peerDependencies:
- postcss: '>=8.0.9'
- ts-node: '>=9.0.0'
- peerDependenciesMeta:
- postcss:
- optional: true
- ts-node:
- optional: true
-
- postcss-nested@6.2.0:
- resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==}
- engines: {node: '>=12.0'}
- peerDependencies:
- postcss: ^8.2.14
-
postcss-selector-parser@6.1.2:
resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
engines: {node: '>=4'}
@@ -6267,9 +6239,6 @@ packages:
resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
engines: {node: '>=0.10.0'}
- read-cache@1.0.0:
- resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
-
read-package-up@11.0.0:
resolution: {integrity: sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==}
engines: {node: '>=18'}
@@ -6278,10 +6247,6 @@ packages:
resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==}
engines: {node: '>=18'}
- readdirp@3.6.0:
- resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
- engines: {node: '>=8.10.0'}
-
recharts-scale@0.4.5:
resolution: {integrity: sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==}
@@ -6706,11 +6671,6 @@ packages:
babel-plugin-macros:
optional: true
- sucrase@3.35.0:
- resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
- engines: {node: '>=16 || 14 >=14.17'}
- hasBin: true
-
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
@@ -6736,31 +6696,33 @@ packages:
resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==}
engines: {node: ^14.18.0 || >=16.0.0}
- tailwind-merge@2.5.4:
- resolution: {integrity: sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==}
-
tailwind-merge@2.6.0:
resolution: {integrity: sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==}
tailwind-merge@3.0.2:
resolution: {integrity: sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw==}
- tailwind-variants@0.3.0:
- resolution: {integrity: sha512-ho2k5kn+LB1fT5XdNS3Clb96zieWxbStE9wNLK7D0AV64kdZMaYzAKo0fWl6fXLPY99ffF9oBJnIj5escEl/8A==}
+ tailwind-merge@3.3.1:
+ resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==}
+
+ tailwind-variants@1.0.0:
+ resolution: {integrity: sha512-2WSbv4ulEEyuBKomOunut65D8UZwxrHoRfYnxGcQNnHqlSCp2+B7Yz2W+yrNDrxRodOXtGD/1oCcKGNBnUqMqA==}
engines: {node: '>=16.x', pnpm: '>=7.x'}
peerDependencies:
tailwindcss: '*'
- tailwind-variants@1.0.0:
- resolution: {integrity: sha512-2WSbv4ulEEyuBKomOunut65D8UZwxrHoRfYnxGcQNnHqlSCp2+B7Yz2W+yrNDrxRodOXtGD/1oCcKGNBnUqMqA==}
+ tailwind-variants@2.0.1:
+ resolution: {integrity: sha512-1wt8c4PWO3jbZcKGBrjIV8cehWarREw1C2os0k8Mcq0nof/CbafNhUUjb0LRWiiRfAvDK6v1deswtHLsygKglw==}
engines: {node: '>=16.x', pnpm: '>=7.x'}
peerDependencies:
+ tailwind-merge: '>=3.0.0'
tailwindcss: '*'
+ peerDependenciesMeta:
+ tailwind-merge:
+ optional: true
- tailwindcss@3.4.17:
- resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==}
- engines: {node: '>=14.0.0'}
- hasBin: true
+ tailwindcss@4.1.12:
+ resolution: {integrity: sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==}
tapable@2.2.1:
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
@@ -6770,6 +6732,10 @@ packages:
resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==}
engines: {node: '>=6'}
+ tar@7.4.3:
+ resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==}
+ engines: {node: '>=18'}
+
temp-dir@2.0.0:
resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==}
engines: {node: '>=8'}
@@ -6799,13 +6765,6 @@ packages:
engines: {node: '>=10'}
hasBin: true
- thenify-all@1.6.0:
- resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
- engines: {node: '>=0.8'}
-
- thenify@3.3.1:
- resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
-
tiny-invariant@1.3.3:
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
@@ -6846,9 +6805,6 @@ packages:
peerDependencies:
typescript: '>=4.8.4'
- ts-interface-checker@0.1.13:
- resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
-
ts-pattern@5.6.2:
resolution: {integrity: sha512-d4IxJUXROL5NCa3amvMg6VQW2HVtZYmUTPfvVtO7zJWGYLJ+mry9v2OmYm+z67aniQoQ8/yFNadiEwtNS9qQiw==}
@@ -7193,15 +7149,14 @@ packages:
yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+ yallist@5.0.0:
+ resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
+ engines: {node: '>=18'}
+
yaml-eslint-parser@1.3.0:
resolution: {integrity: sha512-E/+VitOorXSLiAqtTd7Yqax0/pAS3xaYMP+AUUJGOK1OZG3rhcj9fcJOM5HJ2VrP1FrStVCWr1muTfQCdj4tAA==}
engines: {node: ^14.17.0 || >=16.0.0}
- yaml@2.7.0:
- resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==}
- engines: {node: '>= 14'}
- hasBin: true
-
yaml@2.7.1:
resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==}
engines: {node: '>= 14'}
@@ -7244,49 +7199,49 @@ snapshots:
'@jridgewell/gen-mapping': 0.3.8
'@jridgewell/trace-mapping': 0.3.25
- '@antfu/eslint-config@4.11.0(@eslint-react/eslint-plugin@1.33.0(eslint@9.22.0(jiti@1.21.7))(ts-api-utils@2.1.0(typescript@5.7.3))(typescript@5.7.3))(@typescript-eslint/utils@8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(@vue/compiler-sfc@3.5.13)(eslint-plugin-react-hooks@5.2.0(eslint@9.22.0(jiti@1.21.7)))(eslint-plugin-react-refresh@0.4.20(eslint@9.22.0(jiti@1.21.7)))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)':
+ '@antfu/eslint-config@4.11.0(@eslint-react/eslint-plugin@1.33.0(eslint@9.22.0(jiti@2.5.1))(ts-api-utils@2.1.0(typescript@5.7.3))(typescript@5.7.3))(@typescript-eslint/utils@8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(@vue/compiler-sfc@3.5.13)(eslint-plugin-react-hooks@5.2.0(eslint@9.22.0(jiti@2.5.1)))(eslint-plugin-react-refresh@0.4.20(eslint@9.22.0(jiti@2.5.1)))(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)':
dependencies:
'@antfu/install-pkg': 1.0.0
'@clack/prompts': 0.10.0
- '@eslint-community/eslint-plugin-eslint-comments': 4.4.1(eslint@9.22.0(jiti@1.21.7))
+ '@eslint-community/eslint-plugin-eslint-comments': 4.4.1(eslint@9.22.0(jiti@2.5.1))
'@eslint/markdown': 6.3.0
- '@stylistic/eslint-plugin': 4.2.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@typescript-eslint/eslint-plugin': 8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@typescript-eslint/parser': 8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@vitest/eslint-plugin': 1.1.39(@typescript-eslint/utils@8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@stylistic/eslint-plugin': 4.2.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@typescript-eslint/eslint-plugin': 8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@typescript-eslint/parser': 8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@vitest/eslint-plugin': 1.1.39(@typescript-eslint/utils@8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
ansis: 3.17.0
cac: 6.7.14
- eslint: 9.22.0(jiti@1.21.7)
- eslint-config-flat-gitignore: 2.1.0(eslint@9.22.0(jiti@1.21.7))
+ eslint: 9.22.0(jiti@2.5.1)
+ eslint-config-flat-gitignore: 2.1.0(eslint@9.22.0(jiti@2.5.1))
eslint-flat-config-utils: 2.0.1
- eslint-merge-processors: 2.0.0(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-antfu: 3.1.1(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-command: 3.2.0(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-import-x: 4.10.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint-plugin-jsdoc: 50.6.9(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-jsonc: 2.20.0(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-n: 17.17.0(eslint@9.22.0(jiti@1.21.7))
+ eslint-merge-processors: 2.0.0(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-antfu: 3.1.1(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-command: 3.2.0(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-import-x: 4.10.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint-plugin-jsdoc: 50.6.9(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-jsonc: 2.20.0(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-n: 17.17.0(eslint@9.22.0(jiti@2.5.1))
eslint-plugin-no-only-tests: 3.3.0
- eslint-plugin-perfectionist: 4.11.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint-plugin-pnpm: 0.3.1(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-regexp: 2.7.0(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-toml: 0.12.0(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-unicorn: 57.0.0(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-unused-imports: 4.2.0(@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-vue: 10.0.0(eslint@9.22.0(jiti@1.21.7))(vue-eslint-parser@10.1.2(eslint@9.22.0(jiti@1.21.7)))
- eslint-plugin-yml: 1.17.0(eslint@9.22.0(jiti@1.21.7))
- eslint-processor-vue-blocks: 2.0.0(@vue/compiler-sfc@3.5.13)(eslint@9.22.0(jiti@1.21.7))
+ eslint-plugin-perfectionist: 4.11.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint-plugin-pnpm: 0.3.1(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-regexp: 2.7.0(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-toml: 0.12.0(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-unicorn: 57.0.0(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-unused-imports: 4.2.0(@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-vue: 10.0.0(eslint@9.22.0(jiti@2.5.1))(vue-eslint-parser@10.1.2(eslint@9.22.0(jiti@2.5.1)))
+ eslint-plugin-yml: 1.17.0(eslint@9.22.0(jiti@2.5.1))
+ eslint-processor-vue-blocks: 2.0.0(@vue/compiler-sfc@3.5.13)(eslint@9.22.0(jiti@2.5.1))
globals: 16.3.0
jsonc-eslint-parser: 2.4.0
local-pkg: 1.1.1
parse-gitignore: 2.0.0
toml-eslint-parser: 0.10.0
- vue-eslint-parser: 10.1.2(eslint@9.22.0(jiti@1.21.7))
+ vue-eslint-parser: 10.1.2(eslint@9.22.0(jiti@2.5.1))
yaml-eslint-parser: 1.3.0
optionalDependencies:
- '@eslint-react/eslint-plugin': 1.33.0(eslint@9.22.0(jiti@1.21.7))(ts-api-utils@2.1.0(typescript@5.7.3))(typescript@5.7.3)
- eslint-plugin-react-hooks: 5.2.0(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-react-refresh: 0.4.20(eslint@9.22.0(jiti@1.21.7))
+ '@eslint-react/eslint-plugin': 1.33.0(eslint@9.22.0(jiti@2.5.1))(ts-api-utils@2.1.0(typescript@5.7.3))(typescript@5.7.3)
+ eslint-plugin-react-hooks: 5.2.0(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-react-refresh: 0.4.20(eslint@9.22.0(jiti@2.5.1))
transitivePeerDependencies:
- '@eslint/json'
- '@typescript-eslint/utils'
@@ -8292,30 +8247,30 @@ snapshots:
esquery: 1.6.0
jsdoc-type-pratt-parser: 4.1.0
- '@eslint-community/eslint-plugin-eslint-comments@4.4.1(eslint@9.22.0(jiti@1.21.7))':
+ '@eslint-community/eslint-plugin-eslint-comments@4.4.1(eslint@9.22.0(jiti@2.5.1))':
dependencies:
escape-string-regexp: 4.0.0
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
ignore: 5.3.2
- '@eslint-community/eslint-utils@4.5.1(eslint@9.22.0(jiti@1.21.7))':
+ '@eslint-community/eslint-utils@4.5.1(eslint@9.22.0(jiti@2.5.1))':
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
eslint-visitor-keys: 3.4.3
- '@eslint-community/eslint-utils@4.6.1(eslint@9.22.0(jiti@1.21.7))':
+ '@eslint-community/eslint-utils@4.6.1(eslint@9.22.0(jiti@2.5.1))':
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.1': {}
- '@eslint-react/ast@1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)':
+ '@eslint-react/ast@1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)':
dependencies:
'@eslint-react/eff': 1.33.0
'@typescript-eslint/types': 8.39.1
'@typescript-eslint/typescript-estree': 8.39.1(typescript@5.7.3)
- '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
string-ts: 2.2.1
ts-pattern: 5.6.2
transitivePeerDependencies:
@@ -8323,17 +8278,17 @@ snapshots:
- supports-color
- typescript
- '@eslint-react/core@1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)':
+ '@eslint-react/core@1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)':
dependencies:
- '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@eslint-react/eff': 1.33.0
- '@eslint-react/jsx': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/jsx': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/scope-manager': 8.39.1
- '@typescript-eslint/type-utils': 8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/type-utils': 8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/types': 8.39.1
- '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
birecord: 0.1.1
ts-pattern: 5.6.2
transitivePeerDependencies:
@@ -8343,45 +8298,45 @@ snapshots:
'@eslint-react/eff@1.33.0': {}
- '@eslint-react/eslint-plugin@1.33.0(eslint@9.22.0(jiti@1.21.7))(ts-api-utils@2.1.0(typescript@5.7.3))(typescript@5.7.3)':
+ '@eslint-react/eslint-plugin@1.33.0(eslint@9.22.0(jiti@2.5.1))(ts-api-utils@2.1.0(typescript@5.7.3))(typescript@5.7.3)':
dependencies:
'@eslint-react/eff': 1.33.0
- '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/scope-manager': 8.26.1
- '@typescript-eslint/type-utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/type-utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/types': 8.26.1
- '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint: 9.22.0(jiti@1.21.7)
- eslint-plugin-react-debug: 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint-plugin-react-dom: 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint-plugin-react-hooks-extra: 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint-plugin-react-naming-convention: 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint-plugin-react-web-api: 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint-plugin-react-x: 1.33.0(eslint@9.22.0(jiti@1.21.7))(ts-api-utils@2.1.0(typescript@5.7.3))(typescript@5.7.3)
+ '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint: 9.22.0(jiti@2.5.1)
+ eslint-plugin-react-debug: 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint-plugin-react-dom: 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint-plugin-react-hooks-extra: 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint-plugin-react-naming-convention: 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint-plugin-react-web-api: 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint-plugin-react-x: 1.33.0(eslint@9.22.0(jiti@2.5.1))(ts-api-utils@2.1.0(typescript@5.7.3))(typescript@5.7.3)
optionalDependencies:
typescript: 5.7.3
transitivePeerDependencies:
- supports-color
- ts-api-utils
- '@eslint-react/jsx@1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)':
+ '@eslint-react/jsx@1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)':
dependencies:
- '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@eslint-react/eff': 1.33.0
- '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/scope-manager': 8.39.1
'@typescript-eslint/types': 8.39.1
- '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
ts-pattern: 5.6.2
transitivePeerDependencies:
- eslint
- supports-color
- typescript
- '@eslint-react/shared@1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)':
+ '@eslint-react/shared@1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)':
dependencies:
'@eslint-react/eff': 1.33.0
- '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
picomatch: 4.0.2
ts-pattern: 5.6.2
transitivePeerDependencies:
@@ -8389,13 +8344,13 @@ snapshots:
- supports-color
- typescript
- '@eslint-react/var@1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)':
+ '@eslint-react/var@1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)':
dependencies:
- '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@eslint-react/eff': 1.33.0
'@typescript-eslint/scope-manager': 8.39.1
'@typescript-eslint/types': 8.39.1
- '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
string-ts: 2.2.1
ts-pattern: 5.6.2
transitivePeerDependencies:
@@ -8403,9 +8358,9 @@ snapshots:
- supports-color
- typescript
- '@eslint/compat@1.2.7(eslint@9.22.0(jiti@1.21.7))':
+ '@eslint/compat@1.2.7(eslint@9.22.0(jiti@2.5.1))':
optionalDependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
'@eslint/config-array@0.19.2':
dependencies:
@@ -8512,1125 +8467,984 @@ snapshots:
dependencies:
tslib: 2.8.1
- '@heroui/accordion@2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/aria-utils': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/divider': 2.2.13(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/dom-animation': 2.1.8(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
- '@heroui/framer-utils': 2.1.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-aria-accordion': 2.2.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/button': 3.13.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/tree': 3.8.9(react@19.0.0)
+ '@heroui/accordion@2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/aria-utils': 2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/divider': 2.2.17(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/dom-animation': 2.1.10(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
+ '@heroui/framer-utils': 2.1.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-aria-accordion': 2.2.16(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/tree': 3.9.1(react@19.0.0)
'@react-types/accordion': 3.0.0-alpha.26(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/alert@2.2.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/alert@2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/button': 2.2.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/utils': 3.10.6(react@19.0.0)
+ '@heroui/button': 2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@react-stately/utils': 3.10.8(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
transitivePeerDependencies:
- framer-motion
- '@heroui/aria-utils@2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/aria-utils@2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/react-rsc-utils': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/collections': 3.12.3(react@19.0.0)
- '@react-stately/overlays': 3.6.15(react@19.0.0)
- '@react-types/overlays': 3.8.14(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/collections': 3.12.6(react@19.0.0)
+ '@react-types/overlays': 3.9.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
transitivePeerDependencies:
- '@heroui/theme'
- framer-motion
- '@heroui/autocomplete@2.3.20(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(@types/react@19.0.12)(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/aria-utils': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/button': 2.2.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/form': 2.1.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/input': 2.4.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/listbox': 2.3.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/popover': 2.3.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/scroll-shadow': 2.3.13(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/spinner': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-aria-button': 2.2.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/use-safe-layout-effect': 2.1.7(react@19.0.0)
- '@react-aria/combobox': 3.12.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/i18n': 3.12.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/visually-hidden': 3.8.22(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/combobox': 3.10.4(react@19.0.0)
- '@react-types/combobox': 3.13.4(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/autocomplete@2.3.26(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(@types/react@19.0.12)(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/aria-utils': 2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/button': 2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/form': 2.1.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/input': 2.4.25(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/listbox': 2.3.23(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/popover': 2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/scroll-shadow': 2.3.16(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-safe-layout-effect': 2.1.8(react@19.0.0)
+ '@react-aria/combobox': 3.13.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/combobox': 3.11.0(react@19.0.0)
+ '@react-types/combobox': 3.13.7(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
transitivePeerDependencies:
- '@types/react'
- '@heroui/avatar@2.2.15(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/avatar@2.2.20(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-image': 2.1.9(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-image': 2.1.11(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/badge@2.2.12(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/badge@2.2.15(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/breadcrumbs@2.2.15(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@react-aria/breadcrumbs': 3.5.23(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/breadcrumbs': 3.7.12(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@heroui/breadcrumbs@2.2.20(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@react-aria/breadcrumbs': 3.5.27(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-types/breadcrumbs': 3.7.15(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/button@2.2.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/ripple': 2.2.14(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/spinner': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-aria-button': 2.2.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/button': 3.13.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/button': 3.12.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/button@2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/ripple': 2.2.18(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/spinner': 2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-aria-button': 2.2.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/calendar@2.2.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/button': 2.2.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/dom-animation': 2.1.8(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
- '@heroui/framer-utils': 2.1.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-aria-button': 2.2.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@internationalized/date': 3.8.0
- '@react-aria/calendar': 3.8.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/i18n': 3.12.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/visually-hidden': 3.8.22(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/calendar': 3.8.0(react@19.0.0)
- '@react-stately/utils': 3.10.6(react@19.0.0)
- '@react-types/button': 3.12.0(react@19.0.0)
- '@react-types/calendar': 3.7.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
- '@types/lodash.debounce': 4.0.9
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/calendar@2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/button': 2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/dom-animation': 2.1.10(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
+ '@heroui/framer-utils': 2.1.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-aria-button': 2.2.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@internationalized/date': 3.8.2
+ '@react-aria/calendar': 3.9.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/visually-hidden': 3.8.26(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/calendar': 3.8.3(react@19.0.0)
+ '@react-stately/utils': 3.10.8(react@19.0.0)
+ '@react-types/button': 3.13.0(react@19.0.0)
+ '@react-types/calendar': 3.7.3(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
scroll-into-view-if-needed: 3.0.10
- '@heroui/card@2.2.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/ripple': 2.2.14(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-aria-button': 2.2.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/button': 3.13.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/card@2.2.23(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/ripple': 2.2.18(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-aria-button': 2.2.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/checkbox@2.3.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/form': 2.1.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-callback-ref': 2.1.7(react@19.0.0)
- '@heroui/use-safe-layout-effect': 2.1.7(react@19.0.0)
- '@react-aria/checkbox': 3.15.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/visually-hidden': 3.8.22(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/checkbox': 3.6.13(react@19.0.0)
- '@react-stately/toggle': 3.8.3(react@19.0.0)
- '@react-types/checkbox': 3.9.3(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@heroui/checkbox@2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/form': 2.1.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-callback-ref': 2.1.8(react@19.0.0)
+ '@heroui/use-safe-layout-effect': 2.1.8(react@19.0.0)
+ '@react-aria/checkbox': 3.16.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/checkbox': 3.7.0(react@19.0.0)
+ '@react-stately/toggle': 3.9.0(react@19.0.0)
+ '@react-types/checkbox': 3.10.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/chip@2.2.15(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/checkbox': 3.9.3(react@19.0.0)
+ '@heroui/chip@2.2.20(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/code@2.2.14(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/code@2.2.18(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system-rsc': 2.3.13(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system-rsc': 2.3.17(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/date-input@2.3.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/date-input@2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/form': 2.1.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@internationalized/date': 3.8.0
- '@react-aria/datepicker': 3.14.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/i18n': 3.12.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/datepicker': 3.14.0(react@19.0.0)
- '@react-types/datepicker': 3.12.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@heroui/form': 2.1.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@internationalized/date': 3.8.2
+ '@react-aria/datepicker': 3.15.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/datepicker': 3.15.0(react@19.0.0)
+ '@react-types/datepicker': 3.13.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/date-picker@2.3.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/aria-utils': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/button': 2.2.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/calendar': 2.2.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/date-input': 2.3.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/form': 2.1.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/popover': 2.3.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@internationalized/date': 3.8.0
- '@react-aria/datepicker': 3.14.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/i18n': 3.12.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/datepicker': 3.14.0(react@19.0.0)
- '@react-stately/overlays': 3.6.15(react@19.0.0)
- '@react-stately/utils': 3.10.6(react@19.0.0)
- '@react-types/datepicker': 3.12.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/date-picker@2.3.25(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/aria-utils': 2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/button': 2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/calendar': 2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/date-input': 2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/form': 2.1.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/popover': 2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@internationalized/date': 3.8.2
+ '@react-aria/datepicker': 3.15.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/datepicker': 3.15.0(react@19.0.0)
+ '@react-stately/utils': 3.10.8(react@19.0.0)
+ '@react-types/datepicker': 3.13.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/divider@2.2.13(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/divider@2.2.17(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/react-rsc-utils': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system-rsc': 2.3.13(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@heroui/react-rsc-utils': 2.1.9(react@19.0.0)
+ '@heroui/system-rsc': 2.3.17(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/dom-animation@2.1.8(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))':
+ '@heroui/dom-animation@2.1.10(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))':
dependencies:
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/drawer@2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/drawer@2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/framer-utils': 2.1.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/modal': 2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
+ '@heroui/framer-utils': 2.1.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/modal': 2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
transitivePeerDependencies:
- framer-motion
- '@heroui/dropdown@2.3.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/aria-utils': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/menu': 2.2.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/popover': 2.3.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/menu': 3.18.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/menu': 3.9.3(react@19.0.0)
- '@react-types/menu': 3.10.0(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- react: 19.0.0
- react-dom: 19.0.0(react@19.0.0)
-
- '@heroui/form@2.1.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/dropdown@2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/form': 3.1.3(react@19.0.0)
- '@react-types/form': 3.7.11(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@heroui/aria-utils': 2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/menu': 2.2.23(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/popover': 2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/menu': 3.19.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/menu': 3.9.6(react@19.0.0)
+ '@react-types/menu': 3.10.3(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/framer-utils@2.1.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/form@2.1.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/use-measure': 2.1.7(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@react-stately/form': 3.2.0(react@19.0.0)
+ '@react-types/form': 3.7.14(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- transitivePeerDependencies:
- - '@heroui/theme'
- '@heroui/framer-utils@2.1.20(@heroui/theme@2.4.12(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/framer-utils@2.1.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/system': 2.4.20(@heroui/theme@2.4.12(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@heroui/use-measure': 2.1.8(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
transitivePeerDependencies:
- '@heroui/theme'
- '@heroui/image@2.2.12(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/image@2.2.15(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-image': 2.1.9(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-image': 2.1.11(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/input-otp@2.1.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/form': 2.1.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/form': 3.0.15(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/form': 3.1.3(react@19.0.0)
- '@react-stately/utils': 3.10.6(react@19.0.0)
- '@react-types/textfield': 3.12.1(react@19.0.0)
+ '@heroui/input-otp@2.1.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/form': 2.1.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-form-reset': 2.0.1(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/form': 3.1.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/form': 3.2.0(react@19.0.0)
+ '@react-stately/utils': 3.10.8(react@19.0.0)
+ '@react-types/textfield': 3.12.4(react@19.0.0)
input-otp: 1.4.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/input@2.4.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/form': 2.1.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-safe-layout-effect': 2.1.7(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/textfield': 3.17.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/utils': 3.10.6(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
- '@react-types/textfield': 3.12.1(react@19.0.0)
+ '@heroui/input@2.4.25(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/form': 2.1.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-safe-layout-effect': 2.1.8(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/textfield': 3.18.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/utils': 3.10.8(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
+ '@react-types/textfield': 3.12.4(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
react-textarea-autosize: 8.5.9(@types/react@19.0.12)(react@19.0.0)
transitivePeerDependencies:
- '@types/react'
- '@heroui/kbd@2.2.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/kbd@2.2.19(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system-rsc': 2.3.13(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system-rsc': 2.3.17(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/link@2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-aria-link': 2.2.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/link': 3.8.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/link': 3.6.0(react@19.0.0)
+ '@heroui/link@2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-aria-link': 2.2.19(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-types/link': 3.6.3(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/listbox@2.3.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/aria-utils': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/divider': 2.2.13(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-is-mobile': 2.2.9(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/listbox': 3.14.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/list': 3.12.1(react@19.0.0)
- '@react-types/menu': 3.10.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@heroui/listbox@2.3.23(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/aria-utils': 2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/divider': 2.2.17(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-is-mobile': 2.2.12(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/listbox': 3.14.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/list': 3.12.4(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
'@tanstack/react-virtual': 3.11.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
transitivePeerDependencies:
- framer-motion
- '@heroui/menu@2.2.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/aria-utils': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/divider': 2.2.13(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-is-mobile': 2.2.9(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/menu': 3.18.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/menu': 3.9.3(react@19.0.0)
- '@react-stately/tree': 3.8.9(react@19.0.0)
- '@react-types/menu': 3.10.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@heroui/menu@2.2.23(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/aria-utils': 2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/divider': 2.2.17(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-is-mobile': 2.2.12(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/menu': 3.19.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/tree': 3.9.1(react@19.0.0)
+ '@react-types/menu': 3.10.3(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
transitivePeerDependencies:
- framer-motion
- '@heroui/modal@2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/dom-animation': 2.1.8(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
- '@heroui/framer-utils': 2.1.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-aria-button': 2.2.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/use-aria-modal-overlay': 2.2.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/use-disclosure': 2.2.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/use-draggable': 2.1.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/dialog': 3.5.24(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/overlays': 3.27.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/overlays': 3.6.15(react@19.0.0)
- '@react-types/overlays': 3.8.14(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/modal@2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/dom-animation': 2.1.10(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
+ '@heroui/framer-utils': 2.1.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-aria-button': 2.2.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/use-aria-modal-overlay': 2.2.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/use-disclosure': 2.2.15(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/use-draggable': 2.1.16(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/use-viewport-size': 2.0.1(react@19.0.0)
+ '@react-aria/dialog': 3.5.28(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/overlays': 3.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/overlays': 3.6.18(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/navbar@2.2.17(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/dom-animation': 2.1.8(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
- '@heroui/framer-utils': 2.1.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-scroll-position': 2.1.7(react@19.0.0)
- '@react-aria/button': 3.13.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/overlays': 3.27.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/toggle': 3.8.3(react@19.0.0)
- '@react-stately/utils': 3.10.6(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/navbar@2.2.22(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/dom-animation': 2.1.10(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
+ '@heroui/framer-utils': 2.1.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-resize': 2.1.8(react@19.0.0)
+ '@heroui/use-scroll-position': 2.1.8(react@19.0.0)
+ '@react-aria/button': 3.14.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/overlays': 3.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/toggle': 3.9.0(react@19.0.0)
+ '@react-stately/utils': 3.10.8(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/number-input@2.0.9(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/button': 2.2.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/form': 2.1.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-safe-layout-effect': 2.1.7(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/i18n': 3.12.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/numberfield': 3.11.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/numberfield': 3.9.11(react@19.0.0)
- '@react-stately/utils': 3.10.6(react@19.0.0)
- '@react-types/button': 3.12.0(react@19.0.0)
- '@react-types/numberfield': 3.8.10(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@heroui/number-input@2.0.15(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/button': 2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/form': 2.1.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-safe-layout-effect': 2.1.8(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/numberfield': 3.12.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/numberfield': 3.10.0(react@19.0.0)
+ '@react-types/button': 3.13.0(react@19.0.0)
+ '@react-types/numberfield': 3.8.13(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
transitivePeerDependencies:
- framer-motion
- '@heroui/pagination@2.2.17(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-intersection-observer': 2.2.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/use-pagination': 2.2.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/i18n': 3.12.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/pagination@2.2.22(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-intersection-observer': 2.2.14(react@19.0.0)
+ '@heroui/use-pagination': 2.2.16(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
scroll-into-view-if-needed: 3.0.10
- '@heroui/popover@2.3.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/aria-utils': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/button': 2.2.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/dom-animation': 2.1.8(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
- '@heroui/framer-utils': 2.1.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-aria-button': 2.2.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/use-safe-layout-effect': 2.1.7(react@19.0.0)
- '@react-aria/dialog': 3.5.24(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/overlays': 3.27.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/overlays': 3.6.15(react@19.0.0)
- '@react-types/button': 3.12.0(react@19.0.0)
- '@react-types/overlays': 3.8.14(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- react: 19.0.0
- react-dom: 19.0.0(react@19.0.0)
-
- '@heroui/progress@2.2.15(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-is-mounted': 2.1.7(react@19.0.0)
- '@react-aria/i18n': 3.12.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/progress': 3.4.22(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/progress': 3.5.11(react@19.0.0)
+ '@heroui/popover@2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/aria-utils': 2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/button': 2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/dom-animation': 2.1.10(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
+ '@heroui/framer-utils': 2.1.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-aria-button': 2.2.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/use-aria-overlay': 2.0.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/use-safe-layout-effect': 2.1.8(react@19.0.0)
+ '@react-aria/dialog': 3.5.28(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/overlays': 3.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/overlays': 3.6.18(react@19.0.0)
+ '@react-types/overlays': 3.9.0(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/radio@2.3.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/form': 2.1.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/radio': 3.11.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/visually-hidden': 3.8.22(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/radio': 3.10.12(react@19.0.0)
- '@react-types/radio': 3.8.8(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@heroui/progress@2.2.20(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-is-mounted': 2.1.8(react@19.0.0)
+ '@react-aria/progress': 3.4.25(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-types/progress': 3.5.14(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/react-rsc-utils@2.1.7(react@19.0.0)':
+ '@heroui/radio@2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
+ '@heroui/form': 2.1.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/radio': 3.12.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/visually-hidden': 3.8.26(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/radio': 3.11.0(react@19.0.0)
+ '@react-types/radio': 3.9.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
+ react-dom: 19.0.0(react@19.0.0)
'@heroui/react-rsc-utils@2.1.9(react@19.0.0)':
dependencies:
react: 19.0.0
- '@heroui/react-utils@2.1.10(react@19.0.0)':
- dependencies:
- '@heroui/react-rsc-utils': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- react: 19.0.0
-
'@heroui/react-utils@2.1.12(react@19.0.0)':
dependencies:
'@heroui/react-rsc-utils': 2.1.9(react@19.0.0)
'@heroui/shared-utils': 2.1.10
react: 19.0.0
- '@heroui/react@2.7.8(@types/react@19.0.12)(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(tailwindcss@3.4.17)':
- dependencies:
- '@heroui/accordion': 2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/alert': 2.2.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/autocomplete': 2.3.20(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(@types/react@19.0.12)(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/avatar': 2.2.15(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/badge': 2.2.12(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/breadcrumbs': 2.2.15(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/button': 2.2.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/calendar': 2.2.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/card': 2.2.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/checkbox': 2.3.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/chip': 2.2.15(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/code': 2.2.14(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/date-input': 2.3.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/date-picker': 2.3.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/divider': 2.2.13(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/drawer': 2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/dropdown': 2.3.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/form': 2.1.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/framer-utils': 2.1.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/image': 2.2.12(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/input': 2.4.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/input-otp': 2.1.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/kbd': 2.2.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/link': 2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/listbox': 2.3.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/menu': 2.2.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/modal': 2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/navbar': 2.2.17(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/number-input': 2.0.9(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/pagination': 2.2.17(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/popover': 2.3.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/progress': 2.2.15(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/radio': 2.3.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/ripple': 2.2.14(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/scroll-shadow': 2.3.13(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/select': 2.4.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/skeleton': 2.2.12(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/slider': 2.4.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/snippet': 2.2.20(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/spacer': 2.2.14(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/spinner': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/switch': 2.2.17(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/table': 2.2.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/tabs': 2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/toast': 2.0.9(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/tooltip': 2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/user': 2.2.15(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/visually-hidden': 3.8.22(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react@2.8.2(@types/react@19.0.12)(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(tailwindcss@4.1.12)':
+ dependencies:
+ '@heroui/accordion': 2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/alert': 2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/autocomplete': 2.3.26(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(@types/react@19.0.12)(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/avatar': 2.2.20(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/badge': 2.2.15(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/breadcrumbs': 2.2.20(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/button': 2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/calendar': 2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/card': 2.2.23(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/checkbox': 2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/chip': 2.2.20(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/code': 2.2.18(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/date-input': 2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/date-picker': 2.3.25(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/divider': 2.2.17(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/drawer': 2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/dropdown': 2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/form': 2.1.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/framer-utils': 2.1.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/image': 2.2.15(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/input': 2.4.25(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/input-otp': 2.1.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/kbd': 2.2.19(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/link': 2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/listbox': 2.3.23(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/menu': 2.2.23(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/modal': 2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/navbar': 2.2.22(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/number-input': 2.0.15(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/pagination': 2.2.22(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/popover': 2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/progress': 2.2.20(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/radio': 2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/ripple': 2.2.18(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/scroll-shadow': 2.3.16(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/select': 2.4.25(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/skeleton': 2.2.15(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/slider': 2.4.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/snippet': 2.2.25(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/spacer': 2.2.18(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/spinner': 2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/switch': 2.2.22(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/table': 2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/tabs': 2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/toast': 2.0.14(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/tooltip': 2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/user': 2.2.20(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/visually-hidden': 3.8.26(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
transitivePeerDependencies:
- '@types/react'
- tailwindcss
- '@heroui/ripple@2.2.14(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/ripple@2.2.18(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/dom-animation': 2.1.8(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/dom-animation': 2.1.10(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/scroll-shadow@2.3.13(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/scroll-shadow@2.3.16(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-data-scroll-overflow': 2.2.10(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-data-scroll-overflow': 2.2.11(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/select@2.4.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/aria-utils': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/form': 2.1.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/listbox': 2.3.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/popover': 2.3.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/scroll-shadow': 2.3.13(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/spinner': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-aria-button': 2.2.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/use-aria-multiselect': 2.4.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/use-safe-layout-effect': 2.1.7(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/form': 3.0.15(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/overlays': 3.27.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/visually-hidden': 3.8.22(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
- '@tanstack/react-virtual': 3.11.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/select@2.4.25(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/aria-utils': 2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/form': 2.1.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/listbox': 2.3.23(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/popover': 2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/scroll-shadow': 2.3.16(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/spinner': 2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-aria-button': 2.2.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/use-aria-multiselect': 2.4.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/use-form-reset': 2.0.1(react@19.0.0)
+ '@heroui/use-safe-layout-effect': 2.1.8(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/form': 3.1.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/overlays': 3.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/visually-hidden': 3.8.26(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/shared-icons@2.1.7(react@19.0.0)':
+ '@heroui/shared-icons@2.1.10(react@19.0.0)':
dependencies:
react: 19.0.0
'@heroui/shared-utils@2.1.10': {}
- '@heroui/shared-utils@2.1.7': {}
-
- '@heroui/shared-utils@2.1.9': {}
-
- '@heroui/skeleton@2.2.12(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/skeleton@2.2.15(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/slider@2.4.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/tooltip': 2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/i18n': 3.12.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/slider': 3.7.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/visually-hidden': 3.8.22(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/slider': 3.6.3(react@19.0.0)
+ '@heroui/slider@2.4.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/tooltip': 2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/slider': 3.8.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/visually-hidden': 3.8.26(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/slider': 3.7.0(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
transitivePeerDependencies:
- framer-motion
- '@heroui/snippet@2.2.20(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/button': 2.2.19(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/tooltip': 2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/use-clipboard': 2.1.8(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/snippet@2.2.25(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/button': 2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/tooltip': 2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/use-clipboard': 2.1.9(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/spacer@2.2.14(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/spacer@2.2.18(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system-rsc': 2.3.13(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system-rsc': 2.3.17(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/spinner@2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/spinner@2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/system-rsc': 2.3.13(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/system-rsc': 2.3.17(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
transitivePeerDependencies:
- framer-motion
- '@heroui/switch@2.2.17(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-safe-layout-effect': 2.1.7(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/switch': 3.7.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/visually-hidden': 3.8.22(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/toggle': 3.8.3(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
- react: 19.0.0
- react-dom: 19.0.0(react@19.0.0)
-
- '@heroui/system-rsc@2.3.13(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react@19.0.0)':
+ '@heroui/switch@2.2.22(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@react-types/shared': 3.29.0(react@19.0.0)
- clsx: 1.2.1
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-safe-layout-effect': 2.1.8(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/switch': 3.7.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/visually-hidden': 3.8.26(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/toggle': 3.9.0(react@19.0.0)
react: 19.0.0
+ react-dom: 19.0.0(react@19.0.0)
- '@heroui/system-rsc@2.3.17(@heroui/theme@2.4.12(tailwindcss@3.4.17))(react@19.0.0)':
+ '@heroui/system-rsc@2.3.17(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react@19.0.0)':
dependencies:
- '@heroui/theme': 2.4.12(tailwindcss@3.4.17)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
'@react-types/shared': 3.31.0(react@19.0.0)
clsx: 1.2.1
react: 19.0.0
- '@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/system-rsc': 2.3.13(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react@19.0.0)
- '@internationalized/date': 3.8.0
- '@react-aria/i18n': 3.12.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/overlays': 3.27.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/utils': 3.10.6(react@19.0.0)
- '@react-types/datepicker': 3.12.0(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- react: 19.0.0
- react-dom: 19.0.0(react@19.0.0)
- transitivePeerDependencies:
- - '@heroui/theme'
-
- '@heroui/system@2.4.20(@heroui/theme@2.4.12(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@heroui/react-utils': 2.1.12(react@19.0.0)
- '@heroui/system-rsc': 2.3.17(@heroui/theme@2.4.12(tailwindcss@3.4.17))(react@19.0.0)
+ '@heroui/system-rsc': 2.3.17(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react@19.0.0)
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/overlays': 3.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
transitivePeerDependencies:
- '@heroui/theme'
- '@heroui/table@2.2.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/checkbox': 2.3.18(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/spacer': 2.2.14(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/table': 3.17.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/visually-hidden': 3.8.22(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/table': 3.14.1(react@19.0.0)
- '@react-stately/virtualizer': 4.3.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/grid': 3.3.1(react@19.0.0)
- '@react-types/table': 3.12.0(react@19.0.0)
+ '@heroui/table@2.2.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/checkbox': 2.3.24(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/spacer': 2.2.18(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/table': 3.17.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/visually-hidden': 3.8.26(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/table': 3.14.4(react@19.0.0)
+ '@react-stately/virtualizer': 4.4.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-types/grid': 3.3.4(react@19.0.0)
+ '@react-types/table': 3.13.2(react@19.0.0)
'@tanstack/react-virtual': 3.11.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/tabs@2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/aria-utils': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/framer-utils': 2.1.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-is-mounted': 2.1.7(react@19.0.0)
- '@heroui/use-update-effect': 2.1.7(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/tabs': 3.10.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/tabs': 3.8.1(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
- '@react-types/tabs': 3.3.14(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/tabs@2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/aria-utils': 2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-is-mounted': 2.1.8(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/tabs': 3.10.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/tabs': 3.8.4(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
scroll-into-view-if-needed: 3.0.10
- '@heroui/theme@2.4.12(tailwindcss@3.4.17)':
+ '@heroui/theme@2.4.20(tailwindcss@4.1.12)':
dependencies:
- '@heroui/shared-utils': 2.1.7
+ '@heroui/shared-utils': 2.1.10
clsx: 1.2.1
color: 4.2.3
color2k: 2.0.3
deepmerge: 4.3.1
flat: 5.0.2
- tailwind-merge: 2.5.4
- tailwind-variants: 0.3.0(tailwindcss@3.4.17)
- tailwindcss: 3.4.17
+ tailwind-merge: 3.3.1
+ tailwind-variants: 2.0.1(tailwind-merge@3.3.1)(tailwindcss@4.1.12)
+ tailwindcss: 4.1.12
- '@heroui/theme@2.4.15(tailwindcss@3.4.17)':
+ '@heroui/toast@2.0.14(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/shared-utils': 2.1.9
- clsx: 1.2.1
- color: 4.2.3
- color2k: 2.0.3
- deepmerge: 4.3.1
- flat: 5.0.2
- tailwind-merge: 2.5.4
- tailwind-variants: 0.3.0(tailwindcss@3.4.17)
- tailwindcss: 3.4.17
-
- '@heroui/toast@2.0.9(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-icons': 2.1.7(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/spinner': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-is-mobile': 2.2.9(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/toast': 3.0.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/toast': 3.1.0(react@19.0.0)
- '@react-stately/utils': 3.10.6(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-icons': 2.1.10(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/spinner': 2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-is-mobile': 2.2.12(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/toast': 3.0.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/toast': 3.1.2(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/tooltip@2.2.16(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@heroui/aria-utils': 2.2.16(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/dom-animation': 2.1.8(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
- '@heroui/framer-utils': 2.1.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@heroui/use-safe-layout-effect': 2.1.7(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/overlays': 3.27.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/tooltip': 3.8.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/tooltip': 3.5.3(react@19.0.0)
- '@react-types/overlays': 3.8.14(react@19.0.0)
- '@react-types/tooltip': 3.4.16(react@19.0.0)
- framer-motion: 12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/tooltip@2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ dependencies:
+ '@heroui/aria-utils': 2.2.21(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/dom-animation': 2.1.10(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
+ '@heroui/framer-utils': 2.1.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@heroui/use-aria-overlay': 2.0.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/use-safe-layout-effect': 2.1.8(react@19.0.0)
+ '@react-aria/overlays': 3.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/tooltip': 3.8.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/tooltip': 3.5.6(react@19.0.0)
+ '@react-types/overlays': 3.9.0(react@19.0.0)
+ '@react-types/tooltip': 3.4.19(react@19.0.0)
+ framer-motion: 12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/use-aria-accordion@2.2.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/use-aria-accordion@2.2.16(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/button': 3.13.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/selection': 3.24.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/tree': 3.8.9(react@19.0.0)
+ '@react-aria/button': 3.14.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/selection': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/tree': 3.9.1(react@19.0.0)
'@react-types/accordion': 3.0.0-alpha.26(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
transitivePeerDependencies:
- react-dom
- '@heroui/use-aria-button@2.2.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/use-aria-button@2.2.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/shared-utils': 2.1.9
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/button': 3.12.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-types/button': 3.13.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
transitivePeerDependencies:
- react-dom
- '@heroui/use-aria-link@2.2.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/use-aria-link@2.2.19(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/shared-utils': 2.1.9
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/link': 3.6.0(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-types/link': 3.6.3(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
transitivePeerDependencies:
- react-dom
- '@heroui/use-aria-modal-overlay@2.2.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/use-aria-modal-overlay@2.2.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/overlays': 3.27.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/overlays': 3.6.15(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
- react: 19.0.0
- react-dom: 19.0.0(react@19.0.0)
-
- '@heroui/use-aria-multiselect@2.4.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@react-aria/i18n': 3.12.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/label': 3.7.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/listbox': 3.14.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/menu': 3.18.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/selection': 3.24.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/form': 3.1.3(react@19.0.0)
- '@react-stately/list': 3.12.1(react@19.0.0)
- '@react-stately/menu': 3.9.3(react@19.0.0)
- '@react-types/button': 3.12.0(react@19.0.0)
- '@react-types/overlays': 3.8.14(react@19.0.0)
- '@react-types/select': 3.9.11(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@heroui/use-aria-overlay': 2.0.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/overlays': 3.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/overlays': 3.6.18(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@heroui/use-callback-ref@2.1.6(react@19.0.0)':
+ '@heroui/use-aria-multiselect@2.4.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/use-safe-layout-effect': 2.1.6(react@19.0.0)
+ '@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/label': 3.7.20(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/listbox': 3.14.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/menu': 3.19.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/selection': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/form': 3.2.0(react@19.0.0)
+ '@react-stately/list': 3.12.4(react@19.0.0)
+ '@react-stately/menu': 3.9.6(react@19.0.0)
+ '@react-types/button': 3.13.0(react@19.0.0)
+ '@react-types/overlays': 3.9.0(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
+ react-dom: 19.0.0(react@19.0.0)
- '@heroui/use-callback-ref@2.1.7(react@19.0.0)':
+ '@heroui/use-aria-overlay@2.0.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/use-safe-layout-effect': 2.1.7(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/overlays': 3.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
+ react-dom: 19.0.0(react@19.0.0)
- '@heroui/use-clipboard@2.1.8(react@19.0.0)':
+ '@heroui/use-callback-ref@2.1.8(react@19.0.0)':
dependencies:
+ '@heroui/use-safe-layout-effect': 2.1.8(react@19.0.0)
react: 19.0.0
- '@heroui/use-data-scroll-overflow@2.2.10(react@19.0.0)':
+ '@heroui/use-clipboard@2.1.9(react@19.0.0)':
dependencies:
- '@heroui/shared-utils': 2.1.9
react: 19.0.0
- '@heroui/use-disclosure@2.2.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/use-data-scroll-overflow@2.2.11(react@19.0.0)':
dependencies:
- '@heroui/use-callback-ref': 2.1.7(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/utils': 3.10.6(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
react: 19.0.0
- transitivePeerDependencies:
- - react-dom
- '@heroui/use-disclosure@2.2.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/use-disclosure@2.2.15(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/use-callback-ref': 2.1.6(react@19.0.0)
- '@react-aria/utils': 3.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/utils': 3.10.5(react@19.0.0)
+ '@heroui/use-callback-ref': 2.1.8(react@19.0.0)
+ '@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/utils': 3.10.8(react@19.0.0)
react: 19.0.0
transitivePeerDependencies:
- react-dom
- '@heroui/use-draggable@2.1.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/use-draggable@2.1.16(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
transitivePeerDependencies:
- react-dom
- '@heroui/use-image@2.1.9(react@19.0.0)':
+ '@heroui/use-form-reset@2.0.1(react@19.0.0)':
dependencies:
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/use-safe-layout-effect': 2.1.7(react@19.0.0)
react: 19.0.0
- '@heroui/use-intersection-observer@2.2.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/use-image@2.1.11(react@19.0.0)':
dependencies:
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/ssr': 3.9.8(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/shared': 3.29.0(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/use-safe-layout-effect': 2.1.8(react@19.0.0)
react: 19.0.0
- transitivePeerDependencies:
- - react-dom
- '@heroui/use-is-mobile@2.2.9(react@19.0.0)':
+ '@heroui/use-intersection-observer@2.2.14(react@19.0.0)':
dependencies:
- '@react-aria/ssr': 3.9.8(react@19.0.0)
react: 19.0.0
- '@heroui/use-is-mounted@2.1.7(react@19.0.0)':
+ '@heroui/use-is-mobile@2.2.12(react@19.0.0)':
dependencies:
+ '@react-aria/ssr': 3.9.10(react@19.0.0)
react: 19.0.0
- '@heroui/use-measure@2.1.7(react@19.0.0)':
+ '@heroui/use-is-mounted@2.1.8(react@19.0.0)':
dependencies:
react: 19.0.0
@@ -9638,39 +9452,38 @@ snapshots:
dependencies:
react: 19.0.0
- '@heroui/use-pagination@2.2.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/use-pagination@2.2.16(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/shared-utils': 2.1.9
- '@react-aria/i18n': 3.12.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
transitivePeerDependencies:
- react-dom
- '@heroui/use-safe-layout-effect@2.1.6(react@19.0.0)':
+ '@heroui/use-resize@2.1.8(react@19.0.0)':
dependencies:
react: 19.0.0
- '@heroui/use-safe-layout-effect@2.1.7(react@19.0.0)':
+ '@heroui/use-safe-layout-effect@2.1.8(react@19.0.0)':
dependencies:
react: 19.0.0
- '@heroui/use-scroll-position@2.1.7(react@19.0.0)':
+ '@heroui/use-scroll-position@2.1.8(react@19.0.0)':
dependencies:
react: 19.0.0
- '@heroui/use-update-effect@2.1.7(react@19.0.0)':
+ '@heroui/use-viewport-size@2.0.1(react@19.0.0)':
dependencies:
react: 19.0.0
- '@heroui/user@2.2.15(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@heroui/user@2.2.20(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@heroui/avatar': 2.2.15(@heroui/system@2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.15(tailwindcss@3.4.17))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/react-utils': 2.1.10(react@19.0.0)
- '@heroui/shared-utils': 2.1.9
- '@heroui/system': 2.4.15(@heroui/theme@2.4.15(tailwindcss@3.4.17))(framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@heroui/theme': 2.4.15(tailwindcss@3.4.17)
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/avatar': 2.2.20(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@heroui/theme@2.4.20(tailwindcss@4.1.12))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/react-utils': 2.1.12(react@19.0.0)
+ '@heroui/shared-utils': 2.1.10
+ '@heroui/system': 2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.12))(framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@heroui/theme': 2.4.20(tailwindcss@4.1.12)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -9829,12 +9642,21 @@ snapshots:
wrap-ansi: 8.1.0
wrap-ansi-cjs: wrap-ansi@7.0.0
+ '@isaacs/fs-minipass@4.0.1':
+ dependencies:
+ minipass: 7.1.2
+
'@jridgewell/gen-mapping@0.3.8':
dependencies:
'@jridgewell/set-array': 1.2.1
'@jridgewell/sourcemap-codec': 1.5.0
'@jridgewell/trace-mapping': 0.3.25
+ '@jridgewell/remapping@2.3.5':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.8
+ '@jridgewell/trace-mapping': 0.3.25
+
'@jridgewell/resolve-uri@3.1.2': {}
'@jridgewell/set-array@1.2.1': {}
@@ -10346,122 +10168,112 @@ snapshots:
'@radix-ui/rect@1.1.1': {}
- '@react-aria/breadcrumbs@3.5.23(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/breadcrumbs@3.5.27(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/link': 3.8.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/link': 3.8.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/breadcrumbs': 3.7.12(react@19.0.0)
+ '@react-types/breadcrumbs': 3.7.15(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/button@3.13.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/button@3.14.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/toolbar': 3.0.0-beta.15(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/toolbar': 3.0.0-beta.19(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/toggle': 3.8.3(react@19.0.0)
+ '@react-stately/toggle': 3.9.0(react@19.0.0)
'@react-types/button': 3.13.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/calendar@3.8.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/calendar@3.9.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@internationalized/date': 3.8.0
+ '@internationalized/date': 3.8.2
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/live-announcer': 3.4.2
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/live-announcer': 3.4.4
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/calendar': 3.8.0(react@19.0.0)
- '@react-types/button': 3.12.0(react@19.0.0)
- '@react-types/calendar': 3.7.0(react@19.0.0)
+ '@react-stately/calendar': 3.8.3(react@19.0.0)
+ '@react-types/button': 3.13.0(react@19.0.0)
+ '@react-types/calendar': 3.7.3(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/checkbox@3.15.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/checkbox@3.16.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/form': 3.0.15(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/label': 3.7.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/toggle': 3.11.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/form': 3.1.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/label': 3.7.20(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/toggle': 3.12.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/checkbox': 3.6.13(react@19.0.0)
- '@react-stately/form': 3.1.3(react@19.0.0)
- '@react-stately/toggle': 3.8.3(react@19.0.0)
- '@react-types/checkbox': 3.9.3(react@19.0.0)
+ '@react-stately/checkbox': 3.7.0(react@19.0.0)
+ '@react-stately/form': 3.2.0(react@19.0.0)
+ '@react-stately/toggle': 3.9.0(react@19.0.0)
+ '@react-types/checkbox': 3.10.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/combobox@3.12.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/combobox@3.13.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/listbox': 3.14.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/live-announcer': 3.4.2
- '@react-aria/menu': 3.18.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/listbox': 3.14.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/live-announcer': 3.4.4
+ '@react-aria/menu': 3.19.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/overlays': 3.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/selection': 3.24.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/textfield': 3.17.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/selection': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/textfield': 3.18.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/collections': 3.12.3(react@19.0.0)
- '@react-stately/combobox': 3.10.4(react@19.0.0)
- '@react-stately/form': 3.1.3(react@19.0.0)
+ '@react-stately/collections': 3.12.6(react@19.0.0)
+ '@react-stately/combobox': 3.11.0(react@19.0.0)
+ '@react-stately/form': 3.2.0(react@19.0.0)
'@react-types/button': 3.13.0(react@19.0.0)
- '@react-types/combobox': 3.13.4(react@19.0.0)
+ '@react-types/combobox': 3.13.7(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/datepicker@3.14.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/datepicker@3.15.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@internationalized/date': 3.8.0
+ '@internationalized/date': 3.8.2
'@internationalized/number': 3.6.4
'@internationalized/string': 3.2.7
'@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/form': 3.0.15(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/form': 3.1.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/label': 3.7.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/spinbutton': 3.6.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/label': 3.7.20(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/spinbutton': 3.6.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/datepicker': 3.14.0(react@19.0.0)
- '@react-stately/form': 3.1.3(react@19.0.0)
+ '@react-stately/datepicker': 3.15.0(react@19.0.0)
+ '@react-stately/form': 3.2.0(react@19.0.0)
'@react-types/button': 3.13.0(react@19.0.0)
- '@react-types/calendar': 3.7.0(react@19.0.0)
- '@react-types/datepicker': 3.12.0(react@19.0.0)
- '@react-types/dialog': 3.5.17(react@19.0.0)
+ '@react-types/calendar': 3.7.3(react@19.0.0)
+ '@react-types/datepicker': 3.13.0(react@19.0.0)
+ '@react-types/dialog': 3.5.20(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/dialog@3.5.24(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/dialog@3.5.28(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/overlays': 3.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/dialog': 3.5.17(react@19.0.0)
- '@react-types/shared': 3.31.0(react@19.0.0)
- '@swc/helpers': 0.5.17
- react: 19.0.0
- react-dom: 19.0.0(react@19.0.0)
-
- '@react-aria/focus@3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-types/dialog': 3.5.20(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
- clsx: 2.1.1
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -10475,29 +10287,29 @@ snapshots:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/form@3.0.15(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/form@3.1.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/form': 3.1.3(react@19.0.0)
+ '@react-stately/form': 3.2.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/grid@3.13.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/grid@3.14.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/live-announcer': 3.4.2
- '@react-aria/selection': 3.24.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/live-announcer': 3.4.4
+ '@react-aria/selection': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/collections': 3.12.3(react@19.0.0)
- '@react-stately/grid': 3.11.1(react@19.0.0)
- '@react-stately/selection': 3.20.1(react@19.0.0)
- '@react-types/checkbox': 3.9.3(react@19.0.0)
- '@react-types/grid': 3.3.1(react@19.0.0)
+ '@react-stately/collections': 3.12.6(react@19.0.0)
+ '@react-stately/grid': 3.11.4(react@19.0.0)
+ '@react-stately/selection': 3.20.4(react@19.0.0)
+ '@react-types/checkbox': 3.10.0(react@19.0.0)
+ '@react-types/grid': 3.3.4(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -10529,29 +10341,6 @@ snapshots:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/i18n@3.12.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@internationalized/date': 3.8.0
- '@internationalized/message': 3.1.8
- '@internationalized/number': 3.6.4
- '@internationalized/string': 3.2.7
- '@react-aria/ssr': 3.9.8(react@19.0.0)
- '@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/shared': 3.31.0(react@19.0.0)
- '@swc/helpers': 0.5.17
- react: 19.0.0
- react-dom: 19.0.0(react@19.0.0)
-
- '@react-aria/interactions@3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@react-aria/ssr': 3.9.8(react@19.0.0)
- '@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/flags': 3.1.2
- '@react-types/shared': 3.31.0(react@19.0.0)
- '@swc/helpers': 0.5.17
- react: 19.0.0
- react-dom: 19.0.0(react@19.0.0)
-
'@react-aria/interactions@3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/ssr': 3.9.10(react@19.0.0)
@@ -10562,7 +10351,7 @@ snapshots:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/label@3.7.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/label@3.7.20(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
@@ -10570,7 +10359,7 @@ snapshots:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/landmark@3.0.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/landmark@3.0.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
@@ -10579,80 +10368,64 @@ snapshots:
react-dom: 19.0.0(react@19.0.0)
use-sync-external-store: 1.5.0(react@19.0.0)
- '@react-aria/link@3.8.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/link@3.8.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/link': 3.6.0(react@19.0.0)
+ '@react-types/link': 3.6.3(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/listbox@3.14.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/listbox@3.14.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/label': 3.7.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/selection': 3.24.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/label': 3.7.20(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/selection': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/collections': 3.12.3(react@19.0.0)
- '@react-stately/list': 3.12.1(react@19.0.0)
- '@react-types/listbox': 3.6.0(react@19.0.0)
+ '@react-stately/collections': 3.12.6(react@19.0.0)
+ '@react-stately/list': 3.12.4(react@19.0.0)
+ '@react-types/listbox': 3.7.2(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/live-announcer@3.4.2':
+ '@react-aria/live-announcer@3.4.4':
dependencies:
'@swc/helpers': 0.5.17
- '@react-aria/menu@3.18.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/menu@3.19.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/overlays': 3.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/selection': 3.24.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/selection': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/collections': 3.12.3(react@19.0.0)
- '@react-stately/menu': 3.9.3(react@19.0.0)
- '@react-stately/selection': 3.20.1(react@19.0.0)
- '@react-stately/tree': 3.8.9(react@19.0.0)
+ '@react-stately/collections': 3.12.6(react@19.0.0)
+ '@react-stately/menu': 3.9.6(react@19.0.0)
+ '@react-stately/selection': 3.20.4(react@19.0.0)
+ '@react-stately/tree': 3.9.1(react@19.0.0)
'@react-types/button': 3.13.0(react@19.0.0)
- '@react-types/menu': 3.10.0(react@19.0.0)
- '@react-types/shared': 3.31.0(react@19.0.0)
- '@swc/helpers': 0.5.17
- react: 19.0.0
- react-dom: 19.0.0(react@19.0.0)
-
- '@react-aria/numberfield@3.11.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/spinbutton': 3.6.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/textfield': 3.17.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/form': 3.1.3(react@19.0.0)
- '@react-stately/numberfield': 3.9.11(react@19.0.0)
- '@react-types/button': 3.12.0(react@19.0.0)
- '@react-types/numberfield': 3.8.10(react@19.0.0)
+ '@react-types/menu': 3.10.3(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/overlays@3.27.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/numberfield@3.12.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/ssr': 3.9.8(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/spinbutton': 3.6.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/textfield': 3.18.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/visually-hidden': 3.8.26(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/overlays': 3.6.15(react@19.0.0)
+ '@react-stately/form': 3.2.0(react@19.0.0)
+ '@react-stately/numberfield': 3.10.0(react@19.0.0)
'@react-types/button': 3.13.0(react@19.0.0)
- '@react-types/overlays': 3.8.14(react@19.0.0)
+ '@react-types/numberfield': 3.8.13(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -10674,61 +10447,61 @@ snapshots:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/progress@3.4.22(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/progress@3.4.25(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/label': 3.7.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/label': 3.7.20(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/progress': 3.5.11(react@19.0.0)
+ '@react-types/progress': 3.5.14(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/radio@3.11.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/radio@3.12.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/form': 3.0.15(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/form': 3.1.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/label': 3.7.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/label': 3.7.20(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/radio': 3.10.12(react@19.0.0)
- '@react-types/radio': 3.8.8(react@19.0.0)
+ '@react-stately/radio': 3.11.0(react@19.0.0)
+ '@react-types/radio': 3.9.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/selection@3.24.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/selection@3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/selection': 3.20.1(react@19.0.0)
+ '@react-stately/selection': 3.20.4(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/slider@3.7.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/slider@3.8.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/label': 3.7.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/label': 3.7.20(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/slider': 3.6.3(react@19.0.0)
+ '@react-stately/slider': 3.7.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
- '@react-types/slider': 3.7.10(react@19.0.0)
+ '@react-types/slider': 3.8.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/spinbutton@3.6.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/spinbutton@3.6.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/live-announcer': 3.4.2
+ '@react-aria/live-announcer': 3.4.4
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-types/button': 3.13.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
@@ -10746,88 +10519,88 @@ snapshots:
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-aria/switch@3.7.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/switch@3.7.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/toggle': 3.11.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/toggle': 3.8.3(react@19.0.0)
+ '@react-aria/toggle': 3.12.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-stately/toggle': 3.9.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
- '@react-types/switch': 3.5.10(react@19.0.0)
+ '@react-types/switch': 3.5.13(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/table@3.17.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/table@3.17.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/grid': 3.13.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/grid': 3.14.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/live-announcer': 3.4.2
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/live-announcer': 3.4.4
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/visually-hidden': 3.8.26(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/collections': 3.12.3(react@19.0.0)
+ '@react-stately/collections': 3.12.6(react@19.0.0)
'@react-stately/flags': 3.1.2
- '@react-stately/table': 3.14.1(react@19.0.0)
- '@react-types/checkbox': 3.9.3(react@19.0.0)
- '@react-types/grid': 3.3.1(react@19.0.0)
+ '@react-stately/table': 3.14.4(react@19.0.0)
+ '@react-types/checkbox': 3.10.0(react@19.0.0)
+ '@react-types/grid': 3.3.4(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
- '@react-types/table': 3.12.0(react@19.0.0)
+ '@react-types/table': 3.13.2(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/tabs@3.10.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/tabs@3.10.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/focus': 3.20.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/selection': 3.24.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/selection': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/tabs': 3.8.1(react@19.0.0)
+ '@react-stately/tabs': 3.8.4(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
- '@react-types/tabs': 3.3.14(react@19.0.0)
+ '@react-types/tabs': 3.3.17(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/textfield@3.17.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/textfield@3.18.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/form': 3.0.15(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/label': 3.7.17(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/form': 3.1.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/label': 3.7.20(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/form': 3.1.3(react@19.0.0)
+ '@react-stately/form': 3.2.0(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
- '@react-types/textfield': 3.12.1(react@19.0.0)
+ '@react-types/textfield': 3.12.4(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/toast@3.0.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/toast@3.0.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/landmark': 3.0.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/landmark': 3.0.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/toast': 3.1.0(react@19.0.0)
+ '@react-stately/toast': 3.1.2(react@19.0.0)
'@react-types/button': 3.13.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/toggle@3.11.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/toggle@3.12.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/toggle': 3.8.3(react@19.0.0)
- '@react-types/checkbox': 3.9.3(react@19.0.0)
+ '@react-stately/toggle': 3.9.0(react@19.0.0)
+ '@react-types/checkbox': 3.10.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/toolbar@3.0.0-beta.15(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/toolbar@3.0.0-beta.19(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/focus': 3.21.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/i18n': 3.12.11(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
@@ -10837,36 +10610,14 @@ snapshots:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/tooltip@3.8.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-aria/tooltip@3.8.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@react-aria/interactions': 3.25.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-stately/tooltip': 3.5.3(react@19.0.0)
- '@react-types/shared': 3.31.0(react@19.0.0)
- '@react-types/tooltip': 3.4.16(react@19.0.0)
- '@swc/helpers': 0.5.17
- react: 19.0.0
- react-dom: 19.0.0(react@19.0.0)
-
- '@react-aria/utils@3.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@react-aria/ssr': 3.9.8(react@19.0.0)
- '@react-stately/flags': 3.1.2
- '@react-stately/utils': 3.10.8(react@19.0.0)
- '@react-types/shared': 3.31.0(react@19.0.0)
- '@swc/helpers': 0.5.17
- clsx: 2.1.1
- react: 19.0.0
- react-dom: 19.0.0(react@19.0.0)
-
- '@react-aria/utils@3.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@react-aria/ssr': 3.9.8(react@19.0.0)
- '@react-stately/flags': 3.1.2
- '@react-stately/utils': 3.10.8(react@19.0.0)
+ '@react-stately/tooltip': 3.5.6(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
+ '@react-types/tooltip': 3.4.19(react@19.0.0)
'@swc/helpers': 0.5.17
- clsx: 2.1.1
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -10881,15 +10632,6 @@ snapshots:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-aria/visually-hidden@3.8.22(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
- dependencies:
- '@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@react-types/shared': 3.31.0(react@19.0.0)
- '@swc/helpers': 0.5.17
- react: 19.0.0
- react-dom: 19.0.0(react@19.0.0)
-
'@react-aria/visually-hidden@3.8.26(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/interactions': 3.25.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
@@ -10899,39 +10641,39 @@ snapshots:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@react-stately/calendar@3.8.0(react@19.0.0)':
+ '@react-stately/calendar@3.8.3(react@19.0.0)':
dependencies:
- '@internationalized/date': 3.8.0
+ '@internationalized/date': 3.8.2
'@react-stately/utils': 3.10.8(react@19.0.0)
- '@react-types/calendar': 3.7.0(react@19.0.0)
+ '@react-types/calendar': 3.7.3(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/checkbox@3.6.13(react@19.0.0)':
+ '@react-stately/checkbox@3.7.0(react@19.0.0)':
dependencies:
- '@react-stately/form': 3.1.3(react@19.0.0)
+ '@react-stately/form': 3.2.0(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
- '@react-types/checkbox': 3.9.3(react@19.0.0)
+ '@react-types/checkbox': 3.10.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/collections@3.12.3(react@19.0.0)':
+ '@react-stately/collections@3.12.6(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/combobox@3.10.4(react@19.0.0)':
+ '@react-stately/combobox@3.11.0(react@19.0.0)':
dependencies:
- '@react-stately/collections': 3.12.3(react@19.0.0)
- '@react-stately/form': 3.1.3(react@19.0.0)
- '@react-stately/list': 3.12.1(react@19.0.0)
+ '@react-stately/collections': 3.12.6(react@19.0.0)
+ '@react-stately/form': 3.2.0(react@19.0.0)
+ '@react-stately/list': 3.12.4(react@19.0.0)
'@react-stately/overlays': 3.6.18(react@19.0.0)
- '@react-stately/select': 3.6.12(react@19.0.0)
+ '@react-stately/select': 3.7.0(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
- '@react-types/combobox': 3.13.4(react@19.0.0)
+ '@react-types/combobox': 3.13.7(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -10942,14 +10684,14 @@ snapshots:
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/datepicker@3.14.0(react@19.0.0)':
+ '@react-stately/datepicker@3.15.0(react@19.0.0)':
dependencies:
- '@internationalized/date': 3.8.0
+ '@internationalized/date': 3.8.2
'@internationalized/string': 3.2.7
- '@react-stately/form': 3.1.3(react@19.0.0)
+ '@react-stately/form': 3.2.0(react@19.0.0)
'@react-stately/overlays': 3.6.18(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
- '@react-types/datepicker': 3.12.0(react@19.0.0)
+ '@react-types/datepicker': 3.13.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -10958,51 +10700,44 @@ snapshots:
dependencies:
'@swc/helpers': 0.5.17
- '@react-stately/form@3.1.3(react@19.0.0)':
+ '@react-stately/form@3.2.0(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/grid@3.11.1(react@19.0.0)':
+ '@react-stately/grid@3.11.4(react@19.0.0)':
dependencies:
- '@react-stately/collections': 3.12.3(react@19.0.0)
- '@react-stately/selection': 3.20.1(react@19.0.0)
- '@react-types/grid': 3.3.1(react@19.0.0)
+ '@react-stately/collections': 3.12.6(react@19.0.0)
+ '@react-stately/selection': 3.20.4(react@19.0.0)
+ '@react-types/grid': 3.3.4(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/list@3.12.1(react@19.0.0)':
+ '@react-stately/list@3.12.4(react@19.0.0)':
dependencies:
- '@react-stately/collections': 3.12.3(react@19.0.0)
- '@react-stately/selection': 3.20.1(react@19.0.0)
+ '@react-stately/collections': 3.12.6(react@19.0.0)
+ '@react-stately/selection': 3.20.4(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/menu@3.9.3(react@19.0.0)':
+ '@react-stately/menu@3.9.6(react@19.0.0)':
dependencies:
'@react-stately/overlays': 3.6.18(react@19.0.0)
- '@react-types/menu': 3.10.0(react@19.0.0)
+ '@react-types/menu': 3.10.3(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/numberfield@3.9.11(react@19.0.0)':
+ '@react-stately/numberfield@3.10.0(react@19.0.0)':
dependencies:
'@internationalized/number': 3.6.4
- '@react-stately/form': 3.1.3(react@19.0.0)
- '@react-stately/utils': 3.10.8(react@19.0.0)
- '@react-types/numberfield': 3.8.10(react@19.0.0)
- '@swc/helpers': 0.5.17
- react: 19.0.0
-
- '@react-stately/overlays@3.6.15(react@19.0.0)':
- dependencies:
+ '@react-stately/form': 3.2.0(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
- '@react-types/overlays': 3.8.14(react@19.0.0)
+ '@react-types/numberfield': 3.8.13(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
@@ -11013,108 +10748,98 @@ snapshots:
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/radio@3.10.12(react@19.0.0)':
+ '@react-stately/radio@3.11.0(react@19.0.0)':
dependencies:
- '@react-stately/form': 3.1.3(react@19.0.0)
+ '@react-stately/form': 3.2.0(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
- '@react-types/radio': 3.8.8(react@19.0.0)
+ '@react-types/radio': 3.9.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/select@3.6.12(react@19.0.0)':
+ '@react-stately/select@3.7.0(react@19.0.0)':
dependencies:
- '@react-stately/form': 3.1.3(react@19.0.0)
- '@react-stately/list': 3.12.1(react@19.0.0)
+ '@react-stately/form': 3.2.0(react@19.0.0)
+ '@react-stately/list': 3.12.4(react@19.0.0)
'@react-stately/overlays': 3.6.18(react@19.0.0)
- '@react-types/select': 3.9.11(react@19.0.0)
+ '@react-types/select': 3.10.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/selection@3.20.1(react@19.0.0)':
+ '@react-stately/selection@3.20.4(react@19.0.0)':
dependencies:
- '@react-stately/collections': 3.12.3(react@19.0.0)
+ '@react-stately/collections': 3.12.6(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/slider@3.6.3(react@19.0.0)':
+ '@react-stately/slider@3.7.0(react@19.0.0)':
dependencies:
'@react-stately/utils': 3.10.8(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
- '@react-types/slider': 3.7.10(react@19.0.0)
+ '@react-types/slider': 3.8.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/table@3.14.1(react@19.0.0)':
+ '@react-stately/table@3.14.4(react@19.0.0)':
dependencies:
- '@react-stately/collections': 3.12.3(react@19.0.0)
+ '@react-stately/collections': 3.12.6(react@19.0.0)
'@react-stately/flags': 3.1.2
- '@react-stately/grid': 3.11.1(react@19.0.0)
- '@react-stately/selection': 3.20.1(react@19.0.0)
+ '@react-stately/grid': 3.11.4(react@19.0.0)
+ '@react-stately/selection': 3.20.4(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
- '@react-types/grid': 3.3.1(react@19.0.0)
+ '@react-types/grid': 3.3.4(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
- '@react-types/table': 3.12.0(react@19.0.0)
+ '@react-types/table': 3.13.2(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/tabs@3.8.1(react@19.0.0)':
+ '@react-stately/tabs@3.8.4(react@19.0.0)':
dependencies:
- '@react-stately/list': 3.12.1(react@19.0.0)
+ '@react-stately/list': 3.12.4(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
- '@react-types/tabs': 3.3.14(react@19.0.0)
+ '@react-types/tabs': 3.3.17(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/toast@3.1.0(react@19.0.0)':
+ '@react-stately/toast@3.1.2(react@19.0.0)':
dependencies:
'@swc/helpers': 0.5.17
react: 19.0.0
use-sync-external-store: 1.5.0(react@19.0.0)
- '@react-stately/toggle@3.8.3(react@19.0.0)':
+ '@react-stately/toggle@3.9.0(react@19.0.0)':
dependencies:
'@react-stately/utils': 3.10.8(react@19.0.0)
- '@react-types/checkbox': 3.9.3(react@19.0.0)
+ '@react-types/checkbox': 3.10.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/tooltip@3.5.3(react@19.0.0)':
+ '@react-stately/tooltip@3.5.6(react@19.0.0)':
dependencies:
'@react-stately/overlays': 3.6.18(react@19.0.0)
- '@react-types/tooltip': 3.4.16(react@19.0.0)
+ '@react-types/tooltip': 3.4.19(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/tree@3.8.9(react@19.0.0)':
+ '@react-stately/tree@3.9.1(react@19.0.0)':
dependencies:
- '@react-stately/collections': 3.12.3(react@19.0.0)
- '@react-stately/selection': 3.20.1(react@19.0.0)
+ '@react-stately/collections': 3.12.6(react@19.0.0)
+ '@react-stately/selection': 3.20.4(react@19.0.0)
'@react-stately/utils': 3.10.8(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/utils@3.10.5(react@19.0.0)':
- dependencies:
- '@swc/helpers': 0.5.17
- react: 19.0.0
-
- '@react-stately/utils@3.10.6(react@19.0.0)':
- dependencies:
- '@swc/helpers': 0.5.17
- react: 19.0.0
-
'@react-stately/utils@3.10.8(react@19.0.0)':
dependencies:
'@swc/helpers': 0.5.17
react: 19.0.0
- '@react-stately/virtualizer@4.3.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@react-stately/virtualizer@4.4.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@react-aria/utils': 3.30.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
@@ -11127,14 +10852,9 @@ snapshots:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/breadcrumbs@3.7.12(react@19.0.0)':
- dependencies:
- '@react-types/link': 3.6.0(react@19.0.0)
- '@react-types/shared': 3.31.0(react@19.0.0)
- react: 19.0.0
-
- '@react-types/button@3.12.0(react@19.0.0)':
+ '@react-types/breadcrumbs@3.7.15(react@19.0.0)':
dependencies:
+ '@react-types/link': 3.6.3(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
@@ -11143,68 +10863,63 @@ snapshots:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/calendar@3.7.0(react@19.0.0)':
+ '@react-types/calendar@3.7.3(react@19.0.0)':
dependencies:
- '@internationalized/date': 3.8.0
+ '@internationalized/date': 3.8.2
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/checkbox@3.9.3(react@19.0.0)':
+ '@react-types/checkbox@3.10.0(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/combobox@3.13.4(react@19.0.0)':
+ '@react-types/combobox@3.13.7(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/datepicker@3.12.0(react@19.0.0)':
+ '@react-types/datepicker@3.13.0(react@19.0.0)':
dependencies:
- '@internationalized/date': 3.8.0
- '@react-types/calendar': 3.7.0(react@19.0.0)
+ '@internationalized/date': 3.8.2
+ '@react-types/calendar': 3.7.3(react@19.0.0)
'@react-types/overlays': 3.9.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/dialog@3.5.17(react@19.0.0)':
+ '@react-types/dialog@3.5.20(react@19.0.0)':
dependencies:
'@react-types/overlays': 3.9.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/form@3.7.11(react@19.0.0)':
+ '@react-types/form@3.7.14(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/grid@3.3.1(react@19.0.0)':
+ '@react-types/grid@3.3.4(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/link@3.6.0(react@19.0.0)':
+ '@react-types/link@3.6.3(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/listbox@3.6.0(react@19.0.0)':
+ '@react-types/listbox@3.7.2(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/menu@3.10.0(react@19.0.0)':
+ '@react-types/menu@3.10.3(react@19.0.0)':
dependencies:
'@react-types/overlays': 3.9.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/numberfield@3.8.10(react@19.0.0)':
- dependencies:
- '@react-types/shared': 3.31.0(react@19.0.0)
- react: 19.0.0
-
- '@react-types/overlays@3.8.14(react@19.0.0)':
+ '@react-types/numberfield@3.8.13(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
@@ -11214,17 +10929,17 @@ snapshots:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/progress@3.5.11(react@19.0.0)':
+ '@react-types/progress@3.5.14(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/radio@3.8.8(react@19.0.0)':
+ '@react-types/radio@3.9.0(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/select@3.9.11(react@19.0.0)':
+ '@react-types/select@3.10.0(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
@@ -11241,35 +10956,35 @@ snapshots:
dependencies:
react: 19.0.0
- '@react-types/slider@3.7.10(react@19.0.0)':
+ '@react-types/slider@3.8.0(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/switch@3.5.10(react@19.0.0)':
+ '@react-types/switch@3.5.13(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/table@3.12.0(react@19.0.0)':
+ '@react-types/table@3.13.2(react@19.0.0)':
dependencies:
- '@react-types/grid': 3.3.1(react@19.0.0)
+ '@react-types/grid': 3.3.4(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/tabs@3.3.14(react@19.0.0)':
+ '@react-types/tabs@3.3.17(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/textfield@3.12.1(react@19.0.0)':
+ '@react-types/textfield@3.12.4(react@19.0.0)':
dependencies:
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
- '@react-types/tooltip@3.4.16(react@19.0.0)':
+ '@react-types/tooltip@3.4.19(react@19.0.0)':
dependencies:
- '@react-types/overlays': 3.8.14(react@19.0.0)
+ '@react-types/overlays': 3.9.0(react@19.0.0)
'@react-types/shared': 3.31.0(react@19.0.0)
react: 19.0.0
@@ -11350,10 +11065,10 @@ snapshots:
optionalDependencies:
typescript: 5.7.3
- '@stylistic/eslint-plugin@4.2.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)':
+ '@stylistic/eslint-plugin@4.2.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)':
dependencies:
- '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint: 9.22.0(jiti@1.21.7)
+ '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint: 9.22.0(jiti@2.5.1)
eslint-visitor-keys: 4.2.0
espree: 10.3.0
estraverse: 5.3.0
@@ -11386,6 +11101,78 @@ snapshots:
'@tabler/icons@3.33.0': {}
+ '@tailwindcss/node@4.1.12':
+ dependencies:
+ '@jridgewell/remapping': 2.3.5
+ enhanced-resolve: 5.18.3
+ jiti: 2.5.1
+ lightningcss: 1.30.1
+ magic-string: 0.30.17
+ source-map-js: 1.2.1
+ tailwindcss: 4.1.12
+
+ '@tailwindcss/oxide-android-arm64@4.1.12':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-arm64@4.1.12':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-x64@4.1.12':
+ optional: true
+
+ '@tailwindcss/oxide-freebsd-x64@4.1.12':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.12':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.1.12':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.1.12':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.1.12':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-musl@4.1.12':
+ optional: true
+
+ '@tailwindcss/oxide-wasm32-wasi@4.1.12':
+ optional: true
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.1.12':
+ optional: true
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.1.12':
+ optional: true
+
+ '@tailwindcss/oxide@4.1.12':
+ dependencies:
+ detect-libc: 2.0.4
+ tar: 7.4.3
+ optionalDependencies:
+ '@tailwindcss/oxide-android-arm64': 4.1.12
+ '@tailwindcss/oxide-darwin-arm64': 4.1.12
+ '@tailwindcss/oxide-darwin-x64': 4.1.12
+ '@tailwindcss/oxide-freebsd-x64': 4.1.12
+ '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.12
+ '@tailwindcss/oxide-linux-arm64-gnu': 4.1.12
+ '@tailwindcss/oxide-linux-arm64-musl': 4.1.12
+ '@tailwindcss/oxide-linux-x64-gnu': 4.1.12
+ '@tailwindcss/oxide-linux-x64-musl': 4.1.12
+ '@tailwindcss/oxide-wasm32-wasi': 4.1.12
+ '@tailwindcss/oxide-win32-arm64-msvc': 4.1.12
+ '@tailwindcss/oxide-win32-x64-msvc': 4.1.12
+
+ '@tailwindcss/postcss@4.1.12':
+ dependencies:
+ '@alloc/quick-lru': 5.2.0
+ '@tailwindcss/node': 4.1.12
+ '@tailwindcss/oxide': 4.1.12
+ postcss: 8.5.6
+ tailwindcss: 4.1.12
+
'@tanstack/react-virtual@3.11.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@tanstack/virtual-core': 3.11.3
@@ -11657,10 +11444,6 @@ snapshots:
'@types/json5@0.0.29': {}
- '@types/lodash.debounce@4.0.9':
- dependencies:
- '@types/lodash': 4.17.16
-
'@types/lodash@4.17.16': {}
'@types/mdast@4.0.4':
@@ -11701,15 +11484,15 @@ snapshots:
'@types/uuid@10.0.0': {}
- '@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)':
+ '@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/parser': 8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/scope-manager': 8.31.1
- '@typescript-eslint/type-utils': 8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/type-utils': 8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/visitor-keys': 8.31.1
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
graphemer: 1.4.0
ignore: 5.3.2
natural-compare: 1.4.0
@@ -11718,14 +11501,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)':
+ '@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.39.1
'@typescript-eslint/types': 8.39.1
'@typescript-eslint/typescript-estree': 8.39.1(typescript@5.7.3)
'@typescript-eslint/visitor-keys': 8.39.1
debug: 4.4.1
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
typescript: 5.7.3
transitivePeerDependencies:
- supports-color
@@ -11758,23 +11541,23 @@ snapshots:
dependencies:
typescript: 5.7.3
- '@typescript-eslint/type-utils@8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)':
+ '@typescript-eslint/type-utils@8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)':
dependencies:
'@typescript-eslint/typescript-estree': 8.26.1(typescript@5.7.3)
- '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
debug: 4.4.1
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
ts-api-utils: 2.1.0(typescript@5.7.3)
typescript: 5.7.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/type-utils@8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)':
+ '@typescript-eslint/type-utils@8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)':
dependencies:
'@typescript-eslint/typescript-estree': 8.31.1(typescript@5.7.3)
- '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
debug: 4.4.1
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
ts-api-utils: 2.1.0(typescript@5.7.3)
typescript: 5.7.3
transitivePeerDependencies:
@@ -11830,24 +11613,24 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)':
+ '@typescript-eslint/utils@8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)':
dependencies:
- '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@1.21.7))
+ '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@2.5.1))
'@typescript-eslint/scope-manager': 8.26.1
'@typescript-eslint/types': 8.26.1
'@typescript-eslint/typescript-estree': 8.26.1(typescript@5.7.3)
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
typescript: 5.7.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)':
+ '@typescript-eslint/utils@8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)':
dependencies:
- '@eslint-community/eslint-utils': 4.6.1(eslint@9.22.0(jiti@1.21.7))
+ '@eslint-community/eslint-utils': 4.6.1(eslint@9.22.0(jiti@2.5.1))
'@typescript-eslint/scope-manager': 8.31.1
'@typescript-eslint/types': 8.31.1
'@typescript-eslint/typescript-estree': 8.31.1(typescript@5.7.3)
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
typescript: 5.7.3
transitivePeerDependencies:
- supports-color
@@ -12058,10 +11841,10 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.3.3':
optional: true
- '@vitest/eslint-plugin@1.1.39(@typescript-eslint/utils@8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)':
+ '@vitest/eslint-plugin@1.1.39(@typescript-eslint/utils@8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)':
dependencies:
- '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint: 9.22.0(jiti@1.21.7)
+ '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint: 9.22.0(jiti@2.5.1)
optionalDependencies:
typescript: 5.7.3
@@ -12224,17 +12007,8 @@ snapshots:
ansis@3.17.0: {}
- any-promise@1.3.0: {}
-
- anymatch@3.1.3:
- dependencies:
- normalize-path: 3.0.0
- picomatch: 2.3.1
-
are-docs-informative@0.0.2: {}
- arg@5.0.2: {}
-
argparse@2.0.1: {}
aria-hidden@1.2.6:
@@ -12394,8 +12168,6 @@ snapshots:
big.js@5.2.2: {}
- binary-extensions@2.3.0: {}
-
birecord@0.1.1: {}
boolbase@1.0.0: {}
@@ -12451,8 +12223,6 @@ snapshots:
callsites@3.1.0: {}
- camelcase-css@2.0.1: {}
-
caniuse-lite@1.0.30001709: {}
caniuse-lite@1.0.30001731: {}
@@ -12474,17 +12244,7 @@ snapshots:
character-reference-invalid@2.0.1: {}
- chokidar@3.6.0:
- dependencies:
- anymatch: 3.1.3
- braces: 3.0.3
- glob-parent: 5.1.2
- is-binary-path: 2.1.0
- is-glob: 4.0.3
- normalize-path: 3.0.0
- readdirp: 3.6.0
- optionalDependencies:
- fsevents: 2.3.3
+ chownr@3.0.0: {}
chrome-trace-event@1.0.4: {}
@@ -12553,8 +12313,6 @@ snapshots:
commander@2.20.3: {}
- commander@4.1.1: {}
-
comment-parser@1.4.1: {}
common-tags@1.8.2: {}
@@ -12705,8 +12463,7 @@ snapshots:
dequal@2.0.3: {}
- detect-libc@2.0.4:
- optional: true
+ detect-libc@2.0.4: {}
detect-node-es@1.1.0: {}
@@ -12714,16 +12471,12 @@ snapshots:
dependencies:
dequal: 2.0.3
- didyoumean@1.2.2: {}
-
dir-glob@3.0.1:
dependencies:
path-type: 4.0.0
direction@2.0.1: {}
- dlv@1.1.3: {}
-
doctrine@2.1.0:
dependencies:
esutils: 2.0.3
@@ -12940,34 +12693,34 @@ snapshots:
escape-string-regexp@5.0.0: {}
- eslint-compat-utils@0.5.1(eslint@9.22.0(jiti@1.21.7)):
+ eslint-compat-utils@0.5.1(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
semver: 7.7.2
- eslint-compat-utils@0.6.5(eslint@9.22.0(jiti@1.21.7)):
+ eslint-compat-utils@0.6.5(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
semver: 7.7.2
- eslint-config-flat-gitignore@2.1.0(eslint@9.22.0(jiti@1.21.7)):
+ eslint-config-flat-gitignore@2.1.0(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- '@eslint/compat': 1.2.7(eslint@9.22.0(jiti@1.21.7))
- eslint: 9.22.0(jiti@1.21.7)
+ '@eslint/compat': 1.2.7(eslint@9.22.0(jiti@2.5.1))
+ eslint: 9.22.0(jiti@2.5.1)
- eslint-config-next@15.4.7(eslint-plugin-import-x@4.10.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3):
+ eslint-config-next@15.4.7(eslint-plugin-import-x@4.10.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3):
dependencies:
'@next/eslint-plugin-next': 15.4.7
'@rushstack/eslint-patch': 1.12.0
- '@typescript-eslint/eslint-plugin': 8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@typescript-eslint/parser': 8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint: 9.22.0(jiti@1.21.7)
+ '@typescript-eslint/eslint-plugin': 8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@typescript-eslint/parser': 8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint: 9.22.0(jiti@2.5.1)
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import-x@4.10.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint-plugin-import@2.32.0)(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-jsx-a11y: 6.10.2(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-react: 7.37.5(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-react-hooks: 5.2.0(eslint@9.22.0(jiti@1.21.7))
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import-x@4.10.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint-plugin-import@2.32.0)(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-jsx-a11y: 6.10.2(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-react: 7.37.5(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-react-hooks: 5.2.0(eslint@9.22.0(jiti@2.5.1))
optionalDependencies:
typescript: 5.7.3
transitivePeerDependencies:
@@ -12975,9 +12728,9 @@ snapshots:
- eslint-plugin-import-x
- supports-color
- eslint-config-prettier@10.1.8(eslint@9.22.0(jiti@1.21.7)):
+ eslint-config-prettier@10.1.8(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
eslint-flat-config-utils@2.0.1:
dependencies:
@@ -12991,73 +12744,73 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@3.10.1(eslint-plugin-import-x@4.10.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint-plugin-import@2.32.0)(eslint@9.22.0(jiti@1.21.7)):
+ eslint-import-resolver-typescript@3.10.1(eslint-plugin-import-x@4.10.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint-plugin-import@2.32.0)(eslint@9.22.0(jiti@2.5.1)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.1
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
get-tsconfig: 4.10.1
is-bun-module: 2.0.0
stable-hash: 0.0.5
tinyglobby: 0.2.14
unrs-resolver: 1.11.1
optionalDependencies:
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.22.0(jiti@1.21.7))
- eslint-plugin-import-x: 4.10.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.22.0(jiti@2.5.1))
+ eslint-plugin-import-x: 4.10.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
transitivePeerDependencies:
- supports-color
- eslint-json-compat-utils@0.2.1(eslint@9.22.0(jiti@1.21.7))(jsonc-eslint-parser@2.4.0):
+ eslint-json-compat-utils@0.2.1(eslint@9.22.0(jiti@2.5.1))(jsonc-eslint-parser@2.4.0):
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
esquery: 1.6.0
jsonc-eslint-parser: 2.4.0
- eslint-merge-processors@2.0.0(eslint@9.22.0(jiti@1.21.7)):
+ eslint-merge-processors@2.0.0(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
- eslint-module-utils@2.12.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.22.0(jiti@1.21.7)):
+ eslint-module-utils@2.12.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.22.0(jiti@2.5.1)):
dependencies:
debug: 3.2.7
optionalDependencies:
- '@typescript-eslint/parser': 8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint: 9.22.0(jiti@1.21.7)
+ '@typescript-eslint/parser': 8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint: 9.22.0(jiti@2.5.1)
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import-x@4.10.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint-plugin-import@2.32.0)(eslint@9.22.0(jiti@1.21.7))
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import-x@4.10.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint-plugin-import@2.32.0)(eslint@9.22.0(jiti@2.5.1))
transitivePeerDependencies:
- supports-color
- eslint-plugin-antfu@3.1.1(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-antfu@3.1.1(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
- eslint-plugin-command@3.2.0(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-command@3.2.0(eslint@9.22.0(jiti@2.5.1)):
dependencies:
'@es-joy/jsdoccomment': 0.50.0
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
- eslint-plugin-es-x@7.8.0(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-es-x@7.8.0(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@1.21.7))
+ '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@2.5.1))
'@eslint-community/regexpp': 4.12.1
- eslint: 9.22.0(jiti@1.21.7)
- eslint-compat-utils: 0.5.1(eslint@9.22.0(jiti@1.21.7))
+ eslint: 9.22.0(jiti@2.5.1)
+ eslint-compat-utils: 0.5.1(eslint@9.22.0(jiti@2.5.1))
- eslint-plugin-es@3.0.1(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-es@3.0.1(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
eslint-utils: 2.1.0
regexpp: 3.2.0
- eslint-plugin-import-x@4.10.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3):
+ eslint-plugin-import-x@4.10.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3):
dependencies:
'@pkgr/core': 0.2.0
'@types/doctrine': 0.0.9
- '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
debug: 4.4.1
doctrine: 3.0.0
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
eslint-import-resolver-node: 0.3.9
get-tsconfig: 4.10.0
is-glob: 4.0.3
@@ -13070,7 +12823,7 @@ snapshots:
- supports-color
- typescript
- eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.22.0(jiti@2.5.1)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -13079,9 +12832,9 @@ snapshots:
array.prototype.flatmap: 1.3.3
debug: 3.2.7
doctrine: 2.1.0
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.22.0(jiti@1.21.7))
+ eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.22.0(jiti@2.5.1))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -13093,26 +12846,26 @@ snapshots:
string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/parser': 8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-jest-dom@5.5.0(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-jest-dom@5.5.0(eslint@9.22.0(jiti@2.5.1)):
dependencies:
'@babel/runtime': 7.26.10
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
requireindex: 1.2.0
- eslint-plugin-jsdoc@50.6.9(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-jsdoc@50.6.9(eslint@9.22.0(jiti@2.5.1)):
dependencies:
'@es-joy/jsdoccomment': 0.49.0
are-docs-informative: 0.0.2
comment-parser: 1.4.1
debug: 4.4.1
escape-string-regexp: 4.0.0
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
espree: 10.3.0
esquery: 1.6.0
parse-imports: 2.2.1
@@ -13122,12 +12875,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-plugin-jsonc@2.20.0(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-jsonc@2.20.0(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@1.21.7))
- eslint: 9.22.0(jiti@1.21.7)
- eslint-compat-utils: 0.6.5(eslint@9.22.0(jiti@1.21.7))
- eslint-json-compat-utils: 0.2.1(eslint@9.22.0(jiti@1.21.7))(jsonc-eslint-parser@2.4.0)
+ '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@2.5.1))
+ eslint: 9.22.0(jiti@2.5.1)
+ eslint-compat-utils: 0.6.5(eslint@9.22.0(jiti@2.5.1))
+ eslint-json-compat-utils: 0.2.1(eslint@9.22.0(jiti@2.5.1))(jsonc-eslint-parser@2.4.0)
espree: 10.3.0
graphemer: 1.4.0
jsonc-eslint-parser: 2.4.0
@@ -13136,7 +12889,7 @@ snapshots:
transitivePeerDependencies:
- '@eslint/json'
- eslint-plugin-jsx-a11y@6.10.2(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-jsx-a11y@6.10.2(eslint@9.22.0(jiti@2.5.1)):
dependencies:
aria-query: 5.3.2
array-includes: 3.1.8
@@ -13146,7 +12899,7 @@ snapshots:
axobject-query: 4.1.0
damerau-levenshtein: 1.0.8
emoji-regex: 9.2.2
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
hasown: 2.0.2
jsx-ast-utils: 3.3.5
language-tags: 1.0.9
@@ -13155,12 +12908,12 @@ snapshots:
safe-regex-test: 1.1.0
string.prototype.includes: 2.0.1
- eslint-plugin-n@17.17.0(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-n@17.17.0(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@1.21.7))
+ '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@2.5.1))
enhanced-resolve: 5.18.1
- eslint: 9.22.0(jiti@1.21.7)
- eslint-plugin-es-x: 7.8.0(eslint@9.22.0(jiti@1.21.7))
+ eslint: 9.22.0(jiti@2.5.1)
+ eslint-plugin-es-x: 7.8.0(eslint@9.22.0(jiti@2.5.1))
get-tsconfig: 4.10.0
globals: 15.15.0
ignore: 5.3.2
@@ -13169,34 +12922,34 @@ snapshots:
eslint-plugin-no-only-tests@3.3.0: {}
- eslint-plugin-node@11.1.0(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-node@11.1.0(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
- eslint-plugin-es: 3.0.1(eslint@9.22.0(jiti@1.21.7))
+ eslint: 9.22.0(jiti@2.5.1)
+ eslint-plugin-es: 3.0.1(eslint@9.22.0(jiti@2.5.1))
eslint-utils: 2.1.0
ignore: 5.3.2
minimatch: 3.1.2
resolve: 1.22.10
semver: 6.3.1
- eslint-plugin-perfectionist@4.11.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3):
+ eslint-plugin-perfectionist@4.11.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3):
dependencies:
'@typescript-eslint/types': 8.39.1
- '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint: 9.22.0(jiti@1.21.7)
+ '@typescript-eslint/utils': 8.31.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint: 9.22.0(jiti@2.5.1)
natural-orderby: 5.0.0
transitivePeerDependencies:
- supports-color
- typescript
- eslint-plugin-playwright@2.2.0(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-playwright@2.2.0(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
globals: 13.24.0
- eslint-plugin-pnpm@0.3.1(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-pnpm@0.3.1(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
find-up-simple: 1.0.1
jsonc-eslint-parser: 2.4.0
pathe: 2.0.3
@@ -13204,29 +12957,29 @@ snapshots:
tinyglobby: 0.2.12
yaml-eslint-parser: 1.3.0
- eslint-plugin-prettier@5.2.3(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.22.0(jiti@1.21.7)))(eslint@9.22.0(jiti@1.21.7))(prettier@3.5.3):
+ eslint-plugin-prettier@5.2.3(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.22.0(jiti@2.5.1)))(eslint@9.22.0(jiti@2.5.1))(prettier@3.5.3):
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
prettier: 3.5.3
prettier-linter-helpers: 1.0.0
synckit: 0.9.2
optionalDependencies:
'@types/eslint': 9.6.1
- eslint-config-prettier: 10.1.8(eslint@9.22.0(jiti@1.21.7))
+ eslint-config-prettier: 10.1.8(eslint@9.22.0(jiti@2.5.1))
- eslint-plugin-react-debug@1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3):
+ eslint-plugin-react-debug@1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3):
dependencies:
- '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/core': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/core': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@eslint-react/eff': 1.33.0
- '@eslint-react/jsx': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/jsx': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/scope-manager': 8.26.1
- '@typescript-eslint/type-utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/type-utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/types': 8.26.1
- '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint: 9.22.0(jiti@1.21.7)
+ '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint: 9.22.0(jiti@2.5.1)
string-ts: 2.2.1
ts-pattern: 5.6.2
optionalDependencies:
@@ -13234,19 +12987,19 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-plugin-react-dom@1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3):
+ eslint-plugin-react-dom@1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3):
dependencies:
- '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/core': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/core': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@eslint-react/eff': 1.33.0
- '@eslint-react/jsx': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/jsx': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/scope-manager': 8.26.1
'@typescript-eslint/types': 8.26.1
- '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
compare-versions: 6.1.1
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
string-ts: 2.2.1
ts-pattern: 5.6.2
optionalDependencies:
@@ -13254,19 +13007,19 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-plugin-react-hooks-extra@1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3):
+ eslint-plugin-react-hooks-extra@1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3):
dependencies:
- '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/core': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/core': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@eslint-react/eff': 1.33.0
- '@eslint-react/jsx': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/jsx': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/scope-manager': 8.26.1
- '@typescript-eslint/type-utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/type-utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/types': 8.26.1
- '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint: 9.22.0(jiti@1.21.7)
+ '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint: 9.22.0(jiti@2.5.1)
string-ts: 2.2.1
ts-pattern: 5.6.2
optionalDependencies:
@@ -13274,23 +13027,23 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-plugin-react-hooks@5.2.0(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-react-hooks@5.2.0(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
- eslint-plugin-react-naming-convention@1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3):
+ eslint-plugin-react-naming-convention@1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3):
dependencies:
- '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/core': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/core': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@eslint-react/eff': 1.33.0
- '@eslint-react/jsx': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/jsx': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/scope-manager': 8.26.1
- '@typescript-eslint/type-utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/type-utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/types': 8.26.1
- '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint: 9.22.0(jiti@1.21.7)
+ '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint: 9.22.0(jiti@2.5.1)
string-ts: 2.2.1
ts-pattern: 5.6.2
optionalDependencies:
@@ -13298,22 +13051,22 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-plugin-react-refresh@0.4.20(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-react-refresh@0.4.20(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
- eslint-plugin-react-web-api@1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3):
+ eslint-plugin-react-web-api@1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3):
dependencies:
- '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/core': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/core': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@eslint-react/eff': 1.33.0
- '@eslint-react/jsx': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/jsx': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/scope-manager': 8.26.1
'@typescript-eslint/types': 8.26.1
- '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint: 9.22.0(jiti@1.21.7)
+ '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint: 9.22.0(jiti@2.5.1)
string-ts: 2.2.1
ts-pattern: 5.6.2
optionalDependencies:
@@ -13321,20 +13074,20 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-plugin-react-x@1.33.0(eslint@9.22.0(jiti@1.21.7))(ts-api-utils@2.1.0(typescript@5.7.3))(typescript@5.7.3):
+ eslint-plugin-react-x@1.33.0(eslint@9.22.0(jiti@2.5.1))(ts-api-utils@2.1.0(typescript@5.7.3))(typescript@5.7.3):
dependencies:
- '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/core': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/ast': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/core': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@eslint-react/eff': 1.33.0
- '@eslint-react/jsx': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@eslint-react/jsx': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/shared': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ '@eslint-react/var': 1.33.0(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/scope-manager': 8.26.1
- '@typescript-eslint/type-utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/type-utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
'@typescript-eslint/types': 8.26.1
- '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
compare-versions: 6.1.1
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
string-ts: 2.2.1
ts-pattern: 5.6.2
optionalDependencies:
@@ -13343,7 +13096,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-plugin-react@7.37.5(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-react@7.37.5(eslint@9.22.0(jiti@2.5.1)):
dependencies:
array-includes: 3.1.8
array.prototype.findlast: 1.2.5
@@ -13351,7 +13104,7 @@ snapshots:
array.prototype.tosorted: 1.1.4
doctrine: 2.1.0
es-iterator-helpers: 1.2.1
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
estraverse: 5.3.0
hasown: 2.0.2
jsx-ast-utils: 3.3.5
@@ -13365,50 +13118,50 @@ snapshots:
string.prototype.matchall: 4.0.12
string.prototype.repeat: 1.0.0
- eslint-plugin-regexp@2.7.0(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-regexp@2.7.0(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@1.21.7))
+ '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@2.5.1))
'@eslint-community/regexpp': 4.12.1
comment-parser: 1.4.1
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
jsdoc-type-pratt-parser: 4.1.0
refa: 0.12.1
regexp-ast-analysis: 0.7.1
scslre: 0.3.0
- eslint-plugin-tailwindcss@3.18.2(tailwindcss@3.4.17):
+ eslint-plugin-tailwindcss@3.18.2(tailwindcss@4.1.12):
dependencies:
fast-glob: 3.3.3
postcss: 8.5.6
- tailwindcss: 3.4.17
+ tailwindcss: 4.1.12
- eslint-plugin-testing-library@7.1.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3):
+ eslint-plugin-testing-library@7.1.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3):
dependencies:
'@typescript-eslint/scope-manager': 8.26.1
- '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
- eslint: 9.22.0(jiti@1.21.7)
+ '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
+ eslint: 9.22.0(jiti@2.5.1)
transitivePeerDependencies:
- supports-color
- typescript
- eslint-plugin-toml@0.12.0(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-toml@0.12.0(eslint@9.22.0(jiti@2.5.1)):
dependencies:
debug: 4.4.1
- eslint: 9.22.0(jiti@1.21.7)
- eslint-compat-utils: 0.6.5(eslint@9.22.0(jiti@1.21.7))
+ eslint: 9.22.0(jiti@2.5.1)
+ eslint-compat-utils: 0.6.5(eslint@9.22.0(jiti@2.5.1))
lodash: 4.17.21
toml-eslint-parser: 0.10.0
transitivePeerDependencies:
- supports-color
- eslint-plugin-unicorn@57.0.0(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-unicorn@57.0.0(eslint@9.22.0(jiti@2.5.1)):
dependencies:
'@babel/helper-validator-identifier': 7.25.9
- '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@1.21.7))
+ '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@2.5.1))
ci-info: 4.2.0
clean-regexp: 1.0.0
core-js-compat: 3.41.0
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
esquery: 1.6.0
globals: 15.15.0
indent-string: 5.0.0
@@ -13421,38 +13174,38 @@ snapshots:
semver: 7.7.2
strip-indent: 4.0.0
- eslint-plugin-unused-imports@4.2.0(@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-unused-imports@4.2.0(@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint@9.22.0(jiti@2.5.1)):
dependencies:
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
optionalDependencies:
- '@typescript-eslint/eslint-plugin': 8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.22.0(jiti@1.21.7))(typescript@5.7.3)
+ '@typescript-eslint/eslint-plugin': 8.31.1(@typescript-eslint/parser@8.39.1(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3))(eslint@9.22.0(jiti@2.5.1))(typescript@5.7.3)
- eslint-plugin-vue@10.0.0(eslint@9.22.0(jiti@1.21.7))(vue-eslint-parser@10.1.2(eslint@9.22.0(jiti@1.21.7))):
+ eslint-plugin-vue@10.0.0(eslint@9.22.0(jiti@2.5.1))(vue-eslint-parser@10.1.2(eslint@9.22.0(jiti@2.5.1))):
dependencies:
- '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@1.21.7))
- eslint: 9.22.0(jiti@1.21.7)
+ '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@2.5.1))
+ eslint: 9.22.0(jiti@2.5.1)
natural-compare: 1.4.0
nth-check: 2.1.1
postcss-selector-parser: 6.1.2
semver: 7.7.2
- vue-eslint-parser: 10.1.2(eslint@9.22.0(jiti@1.21.7))
+ vue-eslint-parser: 10.1.2(eslint@9.22.0(jiti@2.5.1))
xml-name-validator: 4.0.0
- eslint-plugin-yml@1.17.0(eslint@9.22.0(jiti@1.21.7)):
+ eslint-plugin-yml@1.17.0(eslint@9.22.0(jiti@2.5.1)):
dependencies:
debug: 4.4.1
escape-string-regexp: 4.0.0
- eslint: 9.22.0(jiti@1.21.7)
- eslint-compat-utils: 0.6.5(eslint@9.22.0(jiti@1.21.7))
+ eslint: 9.22.0(jiti@2.5.1)
+ eslint-compat-utils: 0.6.5(eslint@9.22.0(jiti@2.5.1))
natural-compare: 1.4.0
yaml-eslint-parser: 1.3.0
transitivePeerDependencies:
- supports-color
- eslint-processor-vue-blocks@2.0.0(@vue/compiler-sfc@3.5.13)(eslint@9.22.0(jiti@1.21.7)):
+ eslint-processor-vue-blocks@2.0.0(@vue/compiler-sfc@3.5.13)(eslint@9.22.0(jiti@2.5.1)):
dependencies:
'@vue/compiler-sfc': 3.5.13
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
eslint-scope@5.1.1:
dependencies:
@@ -13476,9 +13229,9 @@ snapshots:
eslint-visitor-keys@4.2.1: {}
- eslint@9.22.0(jiti@1.21.7):
+ eslint@9.22.0(jiti@2.5.1):
dependencies:
- '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@1.21.7))
+ '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@2.5.1))
'@eslint-community/regexpp': 4.12.1
'@eslint/config-array': 0.19.2
'@eslint/config-helpers': 0.1.0
@@ -13514,7 +13267,7 @@ snapshots:
natural-compare: 1.4.0
optionator: 0.9.4
optionalDependencies:
- jiti: 1.21.7
+ jiti: 2.5.1
transitivePeerDependencies:
- supports-color
@@ -13650,10 +13403,10 @@ snapshots:
fraction.js@4.3.7: {}
- framer-motion@12.5.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
+ framer-motion@12.23.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
dependencies:
- motion-dom: 12.5.0
- motion-utils: 12.5.0
+ motion-dom: 12.23.12
+ motion-utils: 12.23.6
tslib: 2.8.1
optionalDependencies:
react: 19.0.0
@@ -14025,10 +13778,6 @@ snapshots:
dependencies:
has-bigints: 1.1.0
- is-binary-path@2.1.0:
- dependencies:
- binary-extensions: 2.3.0
-
is-boolean-object@1.2.2:
dependencies:
call-bound: 1.0.4
@@ -14190,7 +13939,7 @@ snapshots:
merge-stream: 2.0.0
supports-color: 8.1.1
- jiti@1.21.7: {}
+ jiti@2.5.1: {}
js-tokens@4.0.0: {}
@@ -14261,9 +14010,50 @@ snapshots:
prelude-ls: 1.2.1
type-check: 0.4.0
- lilconfig@3.1.3: {}
+ lightningcss-darwin-arm64@1.30.1:
+ optional: true
+
+ lightningcss-darwin-x64@1.30.1:
+ optional: true
+
+ lightningcss-freebsd-x64@1.30.1:
+ optional: true
+
+ lightningcss-linux-arm-gnueabihf@1.30.1:
+ optional: true
+
+ lightningcss-linux-arm64-gnu@1.30.1:
+ optional: true
+
+ lightningcss-linux-arm64-musl@1.30.1:
+ optional: true
+
+ lightningcss-linux-x64-gnu@1.30.1:
+ optional: true
+
+ lightningcss-linux-x64-musl@1.30.1:
+ optional: true
+
+ lightningcss-win32-arm64-msvc@1.30.1:
+ optional: true
+
+ lightningcss-win32-x64-msvc@1.30.1:
+ optional: true
- lines-and-columns@1.2.4: {}
+ lightningcss@1.30.1:
+ dependencies:
+ detect-libc: 2.0.4
+ optionalDependencies:
+ lightningcss-darwin-arm64: 1.30.1
+ lightningcss-darwin-x64: 1.30.1
+ lightningcss-freebsd-x64: 1.30.1
+ lightningcss-linux-arm-gnueabihf: 1.30.1
+ lightningcss-linux-arm64-gnu: 1.30.1
+ lightningcss-linux-arm64-musl: 1.30.1
+ lightningcss-linux-x64-gnu: 1.30.1
+ lightningcss-linux-x64-musl: 1.30.1
+ lightningcss-win32-arm64-msvc: 1.30.1
+ lightningcss-win32-x64-msvc: 1.30.1
loader-runner@4.3.0: {}
@@ -14713,6 +14503,12 @@ snapshots:
minipass@7.1.2: {}
+ minizlib@3.0.2:
+ dependencies:
+ minipass: 7.1.2
+
+ mkdirp@3.0.1: {}
+
mlly@1.7.4:
dependencies:
acorn: 8.14.1
@@ -14720,20 +14516,14 @@ snapshots:
pkg-types: 1.3.1
ufo: 1.5.4
- motion-dom@12.5.0:
+ motion-dom@12.23.12:
dependencies:
- motion-utils: 12.5.0
+ motion-utils: 12.23.6
- motion-utils@12.5.0: {}
+ motion-utils@12.23.6: {}
ms@2.1.3: {}
- mz@2.7.0:
- dependencies:
- any-promise: 1.3.0
- object-assign: 4.1.1
- thenify-all: 1.6.0
-
nanoid@3.3.11: {}
napi-postinstall@0.3.3: {}
@@ -14800,8 +14590,6 @@ snapshots:
semver: 7.7.2
validate-npm-package-license: 3.0.4
- normalize-path@3.0.0: {}
-
normalize-range@0.1.2: {}
nth-check@2.1.1:
@@ -14814,8 +14602,6 @@ snapshots:
object-assign@4.1.1: {}
- object-hash@3.0.0: {}
-
object-inspect@1.13.4: {}
object-keys@1.1.1: {}
@@ -14973,8 +14759,6 @@ snapshots:
pinkie@2.0.4: {}
- pirates@4.0.6: {}
-
pkg-dir@4.2.0:
dependencies:
find-up: 4.1.0
@@ -14999,30 +14783,6 @@ snapshots:
possible-typed-array-names@1.1.0: {}
- postcss-import@15.1.0(postcss@8.5.6):
- dependencies:
- postcss: 8.5.6
- postcss-value-parser: 4.2.0
- read-cache: 1.0.0
- resolve: 1.22.10
-
- postcss-js@4.0.1(postcss@8.5.6):
- dependencies:
- camelcase-css: 2.0.1
- postcss: 8.5.6
-
- postcss-load-config@4.0.2(postcss@8.5.6):
- dependencies:
- lilconfig: 3.1.3
- yaml: 2.7.0
- optionalDependencies:
- postcss: 8.5.6
-
- postcss-nested@6.2.0(postcss@8.5.6):
- dependencies:
- postcss: 8.5.6
- postcss-selector-parser: 6.1.2
-
postcss-selector-parser@6.1.2:
dependencies:
cssesc: 3.0.0
@@ -15195,10 +14955,6 @@ snapshots:
react@19.0.0: {}
- read-cache@1.0.0:
- dependencies:
- pify: 2.3.0
-
read-package-up@11.0.0:
dependencies:
find-up-simple: 1.0.1
@@ -15213,10 +14969,6 @@ snapshots:
type-fest: 4.39.1
unicorn-magic: 0.1.0
- readdirp@3.6.0:
- dependencies:
- picomatch: 2.3.1
-
recharts-scale@0.4.5:
dependencies:
decimal.js-light: 2.5.1
@@ -15776,16 +15528,6 @@ snapshots:
optionalDependencies:
'@babel/core': 7.26.10
- sucrase@3.35.0:
- dependencies:
- '@jridgewell/gen-mapping': 0.3.8
- commander: 4.1.1
- glob: 10.4.5
- lines-and-columns: 1.2.4
- mz: 2.7.0
- pirates: 4.0.6
- ts-interface-checker: 0.1.13
-
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
@@ -15812,53 +15554,38 @@ snapshots:
'@pkgr/core': 0.1.1
tslib: 2.8.1
- tailwind-merge@2.5.4: {}
-
tailwind-merge@2.6.0: {}
tailwind-merge@3.0.2: {}
- tailwind-variants@0.3.0(tailwindcss@3.4.17):
- dependencies:
- tailwind-merge: 2.6.0
- tailwindcss: 3.4.17
+ tailwind-merge@3.3.1: {}
- tailwind-variants@1.0.0(tailwindcss@3.4.17):
+ tailwind-variants@1.0.0(tailwindcss@4.1.12):
dependencies:
tailwind-merge: 3.0.2
- tailwindcss: 3.4.17
+ tailwindcss: 4.1.12
- tailwindcss@3.4.17:
+ tailwind-variants@2.0.1(tailwind-merge@3.3.1)(tailwindcss@4.1.12):
dependencies:
- '@alloc/quick-lru': 5.2.0
- arg: 5.0.2
- chokidar: 3.6.0
- didyoumean: 1.2.2
- dlv: 1.1.3
- fast-glob: 3.3.3
- glob-parent: 6.0.2
- is-glob: 4.0.3
- jiti: 1.21.7
- lilconfig: 3.1.3
- micromatch: 4.0.8
- normalize-path: 3.0.0
- object-hash: 3.0.0
- picocolors: 1.1.1
- postcss: 8.5.6
- postcss-import: 15.1.0(postcss@8.5.6)
- postcss-js: 4.0.1(postcss@8.5.6)
- postcss-load-config: 4.0.2(postcss@8.5.6)
- postcss-nested: 6.2.0(postcss@8.5.6)
- postcss-selector-parser: 6.1.2
- resolve: 1.22.10
- sucrase: 3.35.0
- transitivePeerDependencies:
- - ts-node
+ tailwindcss: 4.1.12
+ optionalDependencies:
+ tailwind-merge: 3.3.1
+
+ tailwindcss@4.1.12: {}
tapable@2.2.1: {}
tapable@2.2.2: {}
+ tar@7.4.3:
+ dependencies:
+ '@isaacs/fs-minipass': 4.0.1
+ chownr: 3.0.0
+ minipass: 7.1.2
+ minizlib: 3.0.2
+ mkdirp: 3.0.1
+ yallist: 5.0.0
+
temp-dir@2.0.0: {}
tempy@0.6.0:
@@ -15884,14 +15611,6 @@ snapshots:
commander: 2.20.3
source-map-support: 0.5.21
- thenify-all@1.6.0:
- dependencies:
- thenify: 3.3.1
-
- thenify@3.3.1:
- dependencies:
- any-promise: 1.3.0
-
tiny-invariant@1.3.3: {}
tinycolor2@1.6.0: {}
@@ -15928,8 +15647,6 @@ snapshots:
dependencies:
typescript: 5.7.3
- ts-interface-checker@0.1.13: {}
-
ts-pattern@5.6.2: {}
tsconfig-paths@3.15.0:
@@ -16193,10 +15910,10 @@ snapshots:
d3-time: 3.1.0
d3-timer: 3.0.1
- vue-eslint-parser@10.1.2(eslint@9.22.0(jiti@1.21.7)):
+ vue-eslint-parser@10.1.2(eslint@9.22.0(jiti@2.5.1)):
dependencies:
debug: 4.4.1
- eslint: 9.22.0(jiti@1.21.7)
+ eslint: 9.22.0(jiti@2.5.1)
eslint-scope: 8.3.0
eslint-visitor-keys: 4.2.0
espree: 10.3.0
@@ -16450,13 +16167,13 @@ snapshots:
yallist@3.1.1: {}
+ yallist@5.0.0: {}
+
yaml-eslint-parser@1.3.0:
dependencies:
eslint-visitor-keys: 3.4.3
yaml: 2.7.1
- yaml@2.7.0: {}
-
yaml@2.7.1: {}
yocto-queue@0.1.0: {}
diff --git a/services/frontend/postcss.config.js b/services/frontend/postcss.config.js
deleted file mode 100644
index 12a703d9..00000000
--- a/services/frontend/postcss.config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-module.exports = {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
- },
-};
diff --git a/services/frontend/postcss.config.mjs b/services/frontend/postcss.config.mjs
new file mode 100644
index 00000000..61e36849
--- /dev/null
+++ b/services/frontend/postcss.config.mjs
@@ -0,0 +1,7 @@
+const config = {
+ plugins: {
+ "@tailwindcss/postcss": {},
+ },
+};
+
+export default config;
diff --git a/services/frontend/styles/globals.css b/services/frontend/styles/globals.css
index b5c61c95..51e8a60a 100644
--- a/services/frontend/styles/globals.css
+++ b/services/frontend/styles/globals.css
@@ -1,3 +1,18 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
+@import "tailwindcss";
+@config "../tailwind.config.ts";
+
+@theme inline {
+ --animate-shine: shine var(--duration) infinite linear;
+
+ @keyframes shine {
+ 0% {
+ background-position: 0% 0%;
+ }
+ 50% {
+ background-position: 100% 100%;
+ }
+ to {
+ background-position: 0% 0%;
+ }
+ }
+}
diff --git a/services/frontend/tailwind.config.ts b/services/frontend/tailwind.config.ts
index 87cace67..8b919552 100644
--- a/services/frontend/tailwind.config.ts
+++ b/services/frontend/tailwind.config.ts
@@ -14,27 +14,9 @@ module.exports = {
mono: ["var(--font-geist-mono)"],
},
animation: {
- "border-beam": "border-beam calc(var(--duration)*1s) infinite linear",
gradient: "gradient 8s linear infinite",
- shine: "shine var(--duration) infinite linear",
},
keyframes: {
- shine: {
- "0%": {
- "background-position": "0% 0%",
- },
- "50%": {
- "background-position": "100% 100%",
- },
- to: {
- "background-position": "0% 0%",
- },
- },
- "border-beam": {
- "100%": {
- "offset-distance": "100%",
- },
- },
gradient: {
to: {
backgroundPosition: "var(--bg-size) 0",
From 997618fd5e51d8d7052f9326892ed7a308fadd38 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Thu, 21 Aug 2025 13:02:09 +0200
Subject: [PATCH 19/45] fix: downgrade @internationalized/date to version 3.7.0
for compatibility
---
services/frontend/package.json | 2 +-
services/frontend/pnpm-lock.yaml | 19 ++++++-------------
2 files changed, 7 insertions(+), 14 deletions(-)
diff --git a/services/frontend/package.json b/services/frontend/package.json
index 62527798..9fd9189c 100644
--- a/services/frontend/package.json
+++ b/services/frontend/package.json
@@ -24,7 +24,7 @@
"@heroui/theme": "2.4.20",
"@heroui/use-disclosure": "2.2.15",
"@iconify/react": "^6.0.0",
- "@internationalized/date": "^3.8.0",
+ "@internationalized/date": "^3.7.0",
"@number-flow/react": "^0.5.7",
"@radix-ui/react-popover": "^1.1.15",
"@react-aria/i18n": "^3.12.7",
diff --git a/services/frontend/pnpm-lock.yaml b/services/frontend/pnpm-lock.yaml
index f6af900e..4cc50033 100644
--- a/services/frontend/pnpm-lock.yaml
+++ b/services/frontend/pnpm-lock.yaml
@@ -51,8 +51,8 @@ importers:
specifier: ^6.0.0
version: 6.0.0(react@19.0.0)
'@internationalized/date':
- specifier: ^3.8.0
- version: 3.8.0
+ specifier: ^3.7.0
+ version: 3.8.2
'@number-flow/react':
specifier: ^0.5.7
version: 0.5.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
@@ -1847,9 +1847,6 @@ packages:
cpu: [x64]
os: [win32]
- '@internationalized/date@3.8.0':
- resolution: {integrity: sha512-J51AJ0fEL68hE4CwGPa6E0PO6JDaVLd8aln48xFCSy7CZkZc96dGEGmLs2OEEbBxcsVZtfrqkXJwI2/MSG8yKw==}
-
'@internationalized/date@3.8.2':
resolution: {integrity: sha512-/wENk7CbvLbkUvX1tu0mwq49CVkkWpkXubGel6birjRPyo6uQ4nQpnq5xZu823zRCwwn82zgHrvgF1vZyvmVgA==}
@@ -9593,17 +9590,13 @@ snapshots:
'@img/sharp-win32-x64@0.34.3':
optional: true
- '@internationalized/date@3.8.0':
- dependencies:
- '@swc/helpers': 0.5.17
-
'@internationalized/date@3.8.2':
dependencies:
'@swc/helpers': 0.5.17
'@internationalized/message@3.1.6':
dependencies:
- '@swc/helpers': 0.5.15
+ '@swc/helpers': 0.5.17
intl-messageformat: 10.7.16
'@internationalized/message@3.1.8':
@@ -9613,7 +9606,7 @@ snapshots:
'@internationalized/number@3.6.0':
dependencies:
- '@swc/helpers': 0.5.15
+ '@swc/helpers': 0.5.17
'@internationalized/number@3.6.4':
dependencies:
@@ -9621,7 +9614,7 @@ snapshots:
'@internationalized/string@3.2.5':
dependencies:
- '@swc/helpers': 0.5.15
+ '@swc/helpers': 0.5.17
'@internationalized/string@3.2.7':
dependencies:
@@ -10330,7 +10323,7 @@ snapshots:
'@react-aria/i18n@3.12.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@internationalized/date': 3.8.0
+ '@internationalized/date': 3.8.2
'@internationalized/message': 3.1.6
'@internationalized/number': 3.6.0
'@internationalized/string': 3.2.5
From 86db1f89ca20af1f7c5ddc9535cf8d7cdbd17615 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Thu, 4 Sep 2025 11:21:10 +0200
Subject: [PATCH 20/45] feat: add migrations for alerts, flows, executions, and
runners models with necessary schema changes
---
.../migrations/11_create_alerts_table.go | 48 ++++++
.../database/migrations/12_flows_alerts.go | 162 ++++++++++++++++++
.../migrations/13_execustions_alert_id.go | 60 +++++++
services/backend/pkg/models/alerts.go | 52 ++++++
.../backend/pkg/models/execution_steps.go | 39 ++++-
services/backend/pkg/models/executions.go | 18 +-
services/backend/pkg/models/flows.go | 101 ++++++++++-
services/backend/pkg/models/runners.go | 56 +++++-
8 files changed, 523 insertions(+), 13 deletions(-)
create mode 100644 services/backend/database/migrations/11_create_alerts_table.go
create mode 100644 services/backend/database/migrations/12_flows_alerts.go
create mode 100644 services/backend/database/migrations/13_execustions_alert_id.go
create mode 100644 services/backend/pkg/models/alerts.go
diff --git a/services/backend/database/migrations/11_create_alerts_table.go b/services/backend/database/migrations/11_create_alerts_table.go
new file mode 100644
index 00000000..20311785
--- /dev/null
+++ b/services/backend/database/migrations/11_create_alerts_table.go
@@ -0,0 +1,48 @@
+package migrations
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
+
+ "github.com/uptrace/bun"
+)
+
+func init() {
+ Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
+ return createAlertsSchema(ctx, db)
+ }, func(ctx context.Context, db *bun.DB) error {
+ return dropAlertsSchema(ctx, db)
+ })
+}
+
+func createAlertsSchema(ctx context.Context, db *bun.DB) error {
+ models := []interface{}{
+ (*models.Alerts)(nil),
+ }
+
+ for _, model := range models {
+ _, err := db.NewCreateTable().Model(model).IfNotExists().Exec(ctx)
+ if err != nil {
+ return fmt.Errorf("failed to create table: %v", err)
+ }
+ }
+
+ return nil
+}
+
+func dropAlertsSchema(ctx context.Context, db *bun.DB) error {
+ models := []interface{}{
+ (*models.Alerts)(nil),
+ }
+
+ for _, model := range models {
+ _, err := db.NewDropTable().Model(model).IfExists().Cascade().Exec(ctx)
+ if err != nil {
+ return fmt.Errorf("failed to drop table: %v", err)
+ }
+ }
+
+ return nil
+}
diff --git a/services/backend/database/migrations/12_flows_alerts.go b/services/backend/database/migrations/12_flows_alerts.go
new file mode 100644
index 00000000..6cb70a16
--- /dev/null
+++ b/services/backend/database/migrations/12_flows_alerts.go
@@ -0,0 +1,162 @@
+package migrations
+
+import (
+ "context"
+ "fmt"
+
+ log "github.com/sirupsen/logrus"
+ "github.com/uptrace/bun"
+)
+
+func init() {
+ Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
+ return addAlertColsToFlows(ctx, db)
+ }, func(ctx context.Context, db *bun.DB) error {
+ return removeAlertColsFromFlows(ctx, db)
+ })
+}
+
+func addAlertColsToFlows(ctx context.Context, db *bun.DB) error {
+ // add patterns column
+ exists, err := columnExists(ctx, db, "flows", "patterns")
+ if err != nil {
+ return fmt.Errorf("failed to check if patterns column exists: %v", err)
+ }
+ if !exists {
+ _, err := db.NewAddColumn().
+ Table("flows").
+ ColumnExpr("patterns JSONB DEFAULT jsonb('[]')").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to add patterns column to flows table: %v", err)
+ }
+ } else {
+ log.Debug("patterns column already exists in flows table")
+ }
+
+ exists, err = columnExists(ctx, db, "flows", "group_alerts")
+ if err != nil {
+ return fmt.Errorf("failed to check if group_alerts column exists: %v", err)
+ }
+ if !exists {
+ _, err := db.NewAddColumn().
+ Table("flows").
+ ColumnExpr("group_alerts BOOLEAN DEFAULT true").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to add group_alerts column to flows table: %v", err)
+ }
+ } else {
+ log.Debug("group_alerts column already exists in flows table")
+ }
+
+ exists, err = columnExists(ctx, db, "flows", "group_alerts_identifier")
+ if err != nil {
+ return fmt.Errorf("failed to check if group_alerts_identifier column exists: %v", err)
+ }
+ if !exists {
+ _, err := db.NewAddColumn().
+ Table("flows").
+ ColumnExpr("group_alerts_identifier TEXT DEFAULT ''").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to add group_alerts_identifier column to flows table: %v", err)
+ }
+ } else {
+ log.Debug("group_alerts_identifier column already exists in flows table")
+ }
+
+ exists, err = columnExists(ctx, db, "flows", "alert_threshold")
+ if err != nil {
+ return fmt.Errorf("failed to check if alert_threshold column exists: %v", err)
+ }
+ if !exists {
+ _, err := db.NewAddColumn().
+ Table("flows").
+ ColumnExpr("alert_threshold INTEGER DEFAULT 0").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to add alert_threshold column to flows table: %v", err)
+ }
+ } else {
+ log.Debug("alert_threshold column already exists in flows table")
+ }
+
+ return nil
+}
+
+func removeAlertColsFromFlows(ctx context.Context, db *bun.DB) error {
+ exists, err := columnExists(ctx, db, "flows", "patterns")
+ if err != nil {
+ return fmt.Errorf("failed to check if patterns column exists: %v", err)
+ }
+ if exists {
+ _, err := db.NewDropColumn().
+ Table("flows").
+ Column("patterns").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to remove patterns column from flows table: %v", err)
+ }
+ } else {
+ log.Debug("patterns column already removed from flows table")
+ }
+
+ exists, err = columnExists(ctx, db, "flows", "group_alerts")
+ if err != nil {
+ return fmt.Errorf("failed to check if group_alerts column exists: %v", err)
+ }
+ if exists {
+ _, err := db.NewDropColumn().
+ Table("flows").
+ Column("group_alerts").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to remove group_alerts column from flows table: %v", err)
+ }
+ } else {
+ log.Debug("group_alerts column already removed from flows table")
+ }
+
+ exists, err = columnExists(ctx, db, "flows", "group_alerts_identifier")
+ if err != nil {
+ return fmt.Errorf("failed to check if group_alerts_identifier column exists: %v", err)
+ }
+ if exists {
+ _, err := db.NewDropColumn().
+ Table("flows").
+ Column("group_alerts_identifier").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to remove group_alerts_identifier column from flows table: %v", err)
+ }
+ } else {
+ log.Debug("group_alerts_identifier column already removed from flows table")
+ }
+
+ exists, err = columnExists(ctx, db, "flows", "alert_threshold")
+ if err != nil {
+ return fmt.Errorf("failed to check if alert_threshold column exists: %v", err)
+ }
+ if exists {
+ _, err := db.NewDropColumn().
+ Table("flows").
+ Column("alert_threshold").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to remove alert_threshold column from flows table: %v", err)
+ }
+ } else {
+ log.Debug("alert_threshold column already removed from flows table")
+ }
+
+ return nil
+}
diff --git a/services/backend/database/migrations/13_execustions_alert_id.go b/services/backend/database/migrations/13_execustions_alert_id.go
new file mode 100644
index 00000000..b52be4a4
--- /dev/null
+++ b/services/backend/database/migrations/13_execustions_alert_id.go
@@ -0,0 +1,60 @@
+package migrations
+
+import (
+ "context"
+ "fmt"
+
+ log "github.com/sirupsen/logrus"
+ "github.com/uptrace/bun"
+)
+
+func init() {
+ Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
+ return addAlertIDToExecutions(ctx, db)
+ }, func(ctx context.Context, db *bun.DB) error {
+ return removeAlertIDFromExecutions(ctx, db)
+ })
+}
+
+func addAlertIDToExecutions(ctx context.Context, db *bun.DB) error {
+ // add alert_id column
+ exists, err := columnExists(ctx, db, "executions", "alert_id")
+ if err != nil {
+ return fmt.Errorf("failed to check if alert_id column exists: %v", err)
+ }
+ if !exists {
+ _, err := db.NewAddColumn().
+ Table("executions").
+ ColumnExpr("alert_id TEXT DEFAULT ''").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to add alert_id column to executions table: %v", err)
+ }
+ } else {
+ log.Debug("alert_id column already exists in executions table")
+ }
+
+ return nil
+}
+
+func removeAlertIDFromExecutions(ctx context.Context, db *bun.DB) error {
+ exists, err := columnExists(ctx, db, "executions", "alert_id")
+ if err != nil {
+ return fmt.Errorf("failed to check if alert_id column exists: %v", err)
+ }
+ if exists {
+ _, err := db.NewDropColumn().
+ Table("executions").
+ Column("alert_id").
+ Exec(ctx)
+
+ if err != nil {
+ return fmt.Errorf("failed to remove alert_id column from executions table: %v", err)
+ }
+ } else {
+ log.Debug("alert_id column already removed from executions table")
+ }
+
+ return nil
+}
diff --git a/services/backend/pkg/models/alerts.go b/services/backend/pkg/models/alerts.go
new file mode 100644
index 00000000..0a1f4d9c
--- /dev/null
+++ b/services/backend/pkg/models/alerts.go
@@ -0,0 +1,52 @@
+package models
+
+import (
+ "encoding/json"
+ "time"
+
+ "github.com/google/uuid"
+ "github.com/uptrace/bun"
+)
+
+type Alerts struct {
+ bun.BaseModel `bun:"table:alerts"`
+
+ ID uuid.UUID `bun:",pk,type:uuid,default:gen_random_uuid()" json:"id"`
+ Name string `bun:"name,type:text,default:''" json:"name"`
+ Status string `bun:"status,type:text,default:''" json:"status"`
+ Payload json.RawMessage `bun:"payload,type:jsonb,default:jsonb('[]')" json:"payload"`
+ FlowID string `bun:"flow_id,type:text,default:''" json:"flow_id"`
+ ExecutionID string `bun:"execution_id,type:text,default:''" json:"execution_id"`
+ RunnerID string `bun:"runner_id,type:text,default:''" json:"runner_id"`
+ ParentID string `bun:"parent_id,type:text,default:''" json:"parent_id"`
+ Plugin string `bun:"plugin,type:text,default:''" json:"plugin"`
+ CreatedAt time.Time `bun:"created_at,type:timestamptz,default:now()" json:"created_at"`
+ Encrypted bool `bun:"encrypted,type:bool,default:false" json:"encrypted"`
+ UpdatedAt time.Time `bun:"updated_at,type:timestamptz" json:"updated_at"`
+ ResolvedAt time.Time `bun:"resolved_at,type:timestamptz" json:"resolved_at"`
+ GroupKey string `bun:"group_key,type:text,default:''" json:"group_key"`
+ SubAlerts []SubAlerts `bun:"sub_alerts,type:jsonb,default:jsonb('[]')" json:"sub_alerts"`
+ Note string `bun:"note,type:text,default:''" json:"note"`
+}
+
+type AlertEndpoints struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Endpoint string `json:"endpoint"`
+ Icon string `json:"icon"`
+ Color string `json:"color"`
+}
+
+type SubAlerts struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Status string `json:"status"`
+ Labels json.RawMessage `json:"labels"`
+ StartedAt time.Time `json:"started_at"`
+ ResolvedAt time.Time `json:"resolved_at"`
+}
+
+type IncomingGroupedAlertsRequest struct {
+ FlowID string `json:"flow_id"`
+ GroupAlertsIdentifier string `json:"group_alerts_identifier"`
+}
diff --git a/services/backend/pkg/models/execution_steps.go b/services/backend/pkg/models/execution_steps.go
index 30204f20..8856b35c 100644
--- a/services/backend/pkg/models/execution_steps.go
+++ b/services/backend/pkg/models/execution_steps.go
@@ -1,9 +1,44 @@
package models
import (
- shared_models "github.com/v1Flows/shared-library/pkg/models"
+ "time"
+
+ "github.com/google/uuid"
+ "github.com/uptrace/bun"
)
type ExecutionSteps struct {
- shared_models.ExecutionSteps
+ bun.BaseModel `bun:"table:execution_steps"`
+
+ ID uuid.UUID `bun:",pk,type:uuid,default:gen_random_uuid()" json:"id"`
+ ExecutionID string `bun:"execution_id,type:text,notnull" json:"execution_id"`
+ Action Action `bun:"action,type:jsonb,default:jsonb('{}')" json:"action"`
+ Messages []Message `bun:"messages,type:jsonb,default:jsonb('[]')" json:"messages"`
+ RunnerID string `bun:"runner_id,type:text,default:''" json:"runner_id"`
+ ParentID string `bun:"parent_id,type:text,default:''" json:"parent_id"`
+ IsHidden bool `bun:"is_hidden,type:bool,default:false" json:"is_hidden"`
+ Status string `bun:"status,type:text,default:''" json:"status"`
+ Encrypted bool `bun:"encrypted,type:bool,default:false" json:"encrypted"`
+ Interactive bool `bun:"interactive,type:bool,default:false" json:"interactive"`
+ Interacted bool `bun:"interacted,type:bool,default:false" json:"interacted"`
+ InteractionApproved bool `bun:"interaction_approved,type:bool,default:false" json:"interaction_approved"`
+ InteractionRejected bool `bun:"interaction_rejected,type:bool,default:false" json:"interaction_rejected"`
+ InteractedBy string `bun:"interacted_by,type:text,default:''" json:"interacted_by"`
+ InteractedAt time.Time `bun:"interacted_at,type:timestamptz" json:"interacted_at"`
+ CanceledBy string `bun:"canceled_by,type:text,default:''" json:"canceled_by"`
+ CanceledAt time.Time `bun:"canceled_at,type:timestamptz" json:"canceled_at"`
+ CreatedAt time.Time `bun:"created_at,type:timestamptz,default:now()" json:"created_at"`
+ StartedAt time.Time `bun:"started_at,type:timestamptz" json:"started_at"`
+ FinishedAt time.Time `bun:"finished_at,type:timestamptz" json:"finished_at"`
+}
+
+type Message struct {
+ Title string `json:"title"`
+ Lines []Line `json:"lines"`
+}
+
+type Line struct {
+ Content string `json:"content"`
+ Color string `json:"color"`
+ Timestamp time.Time `json:"timestamp"`
}
diff --git a/services/backend/pkg/models/executions.go b/services/backend/pkg/models/executions.go
index 5b040202..7c77f5c9 100644
--- a/services/backend/pkg/models/executions.go
+++ b/services/backend/pkg/models/executions.go
@@ -3,14 +3,24 @@ package models
import (
"time"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
+ "github.com/google/uuid"
+ "github.com/uptrace/bun"
)
type Executions struct {
- shared_models.Executions
+ bun.BaseModel `bun:"table:executions"`
- ScheduledAt time.Time `bun:"scheduled_at,type:timestamptz" json:"scheduled_at"`
- TriggeredBy string `bun:"triggered_by,type:text,default:'user'" json:"triggered_by"`
+ ID uuid.UUID `bun:",pk,type:uuid,default:gen_random_uuid()" json:"id"`
+ FlowID string `bun:"flow_id,type:text,default:''" json:"flow_id"`
+ RunnerID string `bun:"runner_id,type:text,default:''" json:"runner_id"`
+ Status string `bun:"status,type:text,default:''" json:"status"`
+ CreatedAt time.Time `bun:"created_at,type:timestamptz,default:now()" json:"created_at"`
+ ExecutedAt time.Time `bun:"executed_at,type:timestamptz" json:"executed_at"`
+ FinishedAt time.Time `bun:"finished_at,type:timestamptz" json:"finished_at"`
+ LastHeartbeat time.Time `bun:"last_heartbeat,type:timestamptz" json:"last_heartbeat"`
+ ScheduledAt time.Time `bun:"scheduled_at,type:timestamptz" json:"scheduled_at"`
+ TriggeredBy string `bun:"triggered_by,type:text,default:'user'" json:"triggered_by"`
+ AlertID string `bun:"alert_id,type:text,default:''" json:"alert_id"`
}
type ExecutionWithSteps struct {
diff --git a/services/backend/pkg/models/flows.go b/services/backend/pkg/models/flows.go
index a1890097..17749e7b 100644
--- a/services/backend/pkg/models/flows.go
+++ b/services/backend/pkg/models/flows.go
@@ -1,13 +1,104 @@
package models
import (
- shared_models "github.com/v1Flows/shared-library/pkg/models"
+ "time"
+
+ "github.com/google/uuid"
+ "github.com/uptrace/bun"
)
type Flows struct {
- shared_models.Flows
+ bun.BaseModel `bun:"table:flows"`
+
+ ID uuid.UUID `bun:",pk,type:uuid,default:gen_random_uuid()" json:"id"`
+ Name string `bun:"name,type:text,notnull" json:"name"`
+ Description string `bun:"description,type:text,default:''" json:"description"`
+ Type string `bun:"type,type:text,default:'default'" json:"type"`
+ ProjectID string `bun:"project_id,type:text,notnull" json:"project_id"`
+ RunnerID string `bun:"runner_id,type:text,default:''" json:"runner_id"`
+ ExecParallel bool `bun:"exec_parallel,type:bool,default:false" json:"exec_parallel"`
+ Actions []Action `bun:"type:jsonb,default:jsonb('[]')" json:"actions"`
+ Maintenance bool `bun:"maintenance,type:bool,default:false" json:"maintenance"`
+ MaintenanceMessage string `bun:"maintenance_message,type:text,default:''" json:"maintenance_message"`
+ Disabled bool `bun:"disabled,type:bool,default:false" json:"disabled"`
+ DisabledReason string `bun:"disabled_reason,type:text,default:''" json:"disabled_reason"`
+ CreatedAt time.Time `bun:"created_at,type:timestamptz,default:now()" json:"created_at"`
+ UpdatedAt time.Time `bun:"updated_at,type:timestamptz" json:"updated_at"`
+ FailurePipelines []FailurePipeline `bun:"type:jsonb,default:jsonb('[]')" json:"failure_pipelines"`
+ FailurePipelineID string `bun:"failure_pipeline_id,type:text,default:''" json:"failure_pipeline_id"`
+ FolderID string `bun:"folder_id,type:text,default:''" json:"folder_id"`
+ ScheduleEveryValue int `bun:"schedule_every_value,type:integer,default:0" json:"schedule_every_value"`
+ ScheduleEveryUnit string `bun:"schedule_every_unit,type:text,default:''" json:"schedule_every_unit"`
+ Patterns []Pattern `bun:"type:jsonb,default:jsonb('[]')" json:"patterns"`
+ GroupAlerts bool `bun:"group_alerts,type:bool,default:true" json:"group_alerts"`
+ GroupAlertsIdentifier string `bun:"group_alerts_identifier,type:text,default:''" json:"group_alerts_identifier"`
+ AlertThreshold int `bun:"alert_threshold,type:int,default:0" json:"alert_threshold"`
+}
+
+type Action struct {
+ ID uuid.UUID `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Plugin string `json:"plugin"`
+ Version string `json:"version"`
+ Icon string `json:"icon"`
+ Category string `json:"category"`
+ Active bool `json:"active"`
+ Params []Params `json:"params"`
+ CustomName string `json:"custom_name"`
+ CustomDescription string `json:"custom_description"`
+ FailurePipelineID string `json:"failure_pipeline_id"`
+ UpdateAvailable bool `json:"update_available"`
+ UpdateVersion string `json:"update_version,omitempty"`
+ UpdatedAction *Action `json:"updated_action,omitempty"`
+ Condition Condition `json:"condition,omitempty"`
+}
+
+type Params struct {
+ Key string `json:"key"`
+ Title string `json:"title"`
+ Description string `json:"description"`
+ Category string `json:"category"`
+ Required bool `json:"required"`
+ Type string `json:"type"`
+ Value string `json:"value"`
+ Default string `json:"default"`
+ Options []Option `json:"options,omitempty"`
+ DependsOn DependsOn `json:"depends_on,omitempty"`
+}
+
+type DependsOn struct {
+ Key string `json:"key"`
+ Value string `json:"value"`
+}
+
+type Option struct {
+ Key string `json:"key"`
+ Value string `json:"value"`
+}
+
+type FailurePipeline struct {
+ ID uuid.UUID `json:"id"`
+ Name string `json:"name"`
+ Actions []Action `json:"actions"`
+ ExecParallel bool `json:"exec_parallel"`
+}
+
+type Condition struct {
+ SelectedActionID string `json:"selected_action_id"`
+ ConditionItems []ConditionItem `json:"condition_items"`
+ CancelExecution bool `json:"cancel_execution"`
+}
+
+type ConditionItem struct {
+ ConditionKey string `json:"condition_key"`
+ ConditionType string `json:"condition_type"`
+ ConditionValue string `json:"condition_value"`
+ ConditionLogic string `json:"condition_logic"` // e.g., "AND", "OR"
+}
- FolderID string `bun:"folder_id,type:text,default:''" json:"folder_id"`
- ScheduleEveryValue int `bun:"schedule_every_value,type:integer,default:0" json:"schedule_every_value"`
- ScheduleEveryUnit string `bun:"schedule_every_unit,type:text,default:''" json:"schedule_every_unit"`
+type Pattern struct {
+ Key string `json:"key"`
+ Value string `json:"value"`
+ Type string `json:"type"`
}
diff --git a/services/backend/pkg/models/runners.go b/services/backend/pkg/models/runners.go
index 327d527a..2590dee5 100644
--- a/services/backend/pkg/models/runners.go
+++ b/services/backend/pkg/models/runners.go
@@ -1,9 +1,61 @@
package models
import (
- shared_models "github.com/v1Flows/shared-library/pkg/models"
+ "time"
+
+ "github.com/google/uuid"
+ "github.com/uptrace/bun"
)
type Runners struct {
- shared_models.Runners
+ bun.BaseModel `bun:"table:runners"`
+
+ ID uuid.UUID `bun:",pk,type:uuid,default:gen_random_uuid()" json:"id"`
+ Name string `bun:"name,type:text,notnull" json:"name"`
+ Registered bool `bun:"registered,type:bool,default:false" json:"registered"`
+ ProjectID string `bun:"project_id,type:text,default:''" json:"project_id"`
+ Version string `bun:"version,type:text,default:''" json:"version"`
+ Mode string `bun:"mode,type:text,default:''" json:"mode"`
+ AutoRunner bool `bun:"auto_runner,type:bool,default:false" json:"auto_runner"`
+ SharedRunner bool `bun:"shared_runner,type:bool,default:false" json:"shared_runner"`
+ LastHeartbeat time.Time `bun:"last_heartbeat,type:timestamptz" json:"last_heartbeat"`
+ ExecutingJob bool `bun:"executing_job,type:bool,default:false" json:"executing_job"`
+ Disabled bool `bun:"disabled,type:bool,default:false" json:"disabled"`
+ DisabledReason string `bun:"disabled_reason,type:text,default:''" json:"disabled_reason"`
+ Plugins []Plugin `bun:"plugins,type:jsonb,default:jsonb('[]')" json:"plugins"`
+ Actions []Action `bun:"actions,type:jsonb,default:jsonb('[]')" json:"actions"`
+ Endpoints []Endpoint `bun:"endpoints,type:jsonb,default:jsonb('[]')" json:"endpoints"`
+ RegisteredAt time.Time `bun:"registered_at,type:timestamptz,default:now()" json:"registered_at"`
+ ExecutedExecutions []string `bun:"executed_executions,type:text[],default:'{}'" json:"executed_executions"`
+ ApiURL string `bun:"api_url,type:text,default:''" json:"api_url"`
+ ApiToken string `bun:"api_token,type:text,default:''" json:"api_token"`
+}
+
+type Endpoint struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Path string `json:"path"`
+ Icon string `json:"icon"`
+ Color string `json:"color"`
+}
+
+type IncomingAutoRunners struct {
+ Registered bool `json:"registered"`
+ Version string `json:"version"`
+ Mode string `json:"mode"`
+ LastHeartbeat time.Time `json:"last_heartbeat"`
+ Plugins []Plugin `json:"plugins"`
+ Actions []Action `json:"actions"`
+ Endpoints []Endpoint `json:"endpoints"`
+ ApiURL string `json:"api_url"`
+ ApiToken string `json:"api_token"`
+}
+
+type Plugin struct {
+ Name string `json:"name"`
+ Type string `json:"type"`
+ Version string `json:"version"`
+ Author string `json:"author"`
+ Action Action `json:"action"`
+ Endpoint Endpoint `json:"endpoint"`
}
From a3f63a67909d93ec824eb65e97f63dcf1a4f7758 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Fri, 5 Sep 2025 22:27:32 +0200
Subject: [PATCH 21/45] feat: add delete alert modal and integrate with alert
details drawer
- Implemented DeleteAlertModal component for confirming alert deletions.
- Integrated DeleteAlertModal into AlertDrawer for managing alert lifecycle.
- Added functionality to simulate alerts with SimulateAlertModal.
- Created animated card component for UI enhancements.
- Developed integrations section with animated marquee for showcasing features.
- Implemented utility hooks for mouse tracking and animations.
- Added server-side functions for fetching, deleting, and simulating alerts.
---
.../checkForFlowActionUpdates.go | 15 +-
.../checkHangingExecutionSteps.go | 5 +-
.../checkHangingExecutions.go | 13 +-
.../checkScheduledExecutions.go | 13 +-
.../scheduleFlowExecutions.go | 9 +-
.../functions/encryption/alert_payload.go | 100 ++++++
.../functions/encryption/old_encryption.go | 6 +-
.../encryption/project_execution_messages.go | 6 +-
.../functions/encryption/project_params.go | 7 +-
.../backend/functions/flow/startExecution.go | 36 +-
services/backend/handlers/alerts/create.go | 104 ++++++
services/backend/handlers/alerts/delete.go | 60 ++++
services/backend/handlers/alerts/get_alert.go | 54 +++
.../backend/handlers/alerts/get_alerts.go | 57 +++
.../handlers/alerts/get_grouped_alerts.go | 66 ++++
services/backend/handlers/alerts/update.go | 101 ++++++
.../backend/handlers/executions/schedule.go | 9 +-
.../handlers/executions/update_step.go | 5 +-
.../flows/add_failure_pipeline_actions.go | 3 +-
.../backend/handlers/flows/delete_alerts.go | 64 ++++
services/backend/handlers/flows/get_alerts.go | 57 +++
.../backend/handlers/flows/start_execution.go | 9 +-
services/backend/handlers/flows/update.go | 15 +
.../flows/update_failure_pipeline_actions.go | 3 +-
services/backend/handlers/runners/register.go | 3 +-
services/backend/router/alerts.go | 34 ++
services/backend/router/flows.go | 5 +
services/backend/router/main.go | 1 +
.../frontend/components/alerts/heading.tsx | 84 +++++
services/frontend/components/alerts/list.tsx | 280 +++++++++++++++
.../components/flows/flow/actions.tsx | 6 +
.../components/flows/flow/details.tsx | 17 +-
.../flows/flow/failure-pipelines.tsx | 35 +-
.../components/flows/flow/heading.tsx | 142 +++++---
.../components/flows/flow/page-client.tsx | 4 +
.../components/flows/flow/settings.tsx | 190 +++++++---
.../frontend/components/flows/flow/tabs.tsx | 24 ++
.../components/modals/alerts/delete.tsx | 125 +++++++
.../components/modals/alerts/details.tsx | 334 ++++++++++++++++++
.../components/modals/alerts/simulate.tsx | 181 ++++++++++
.../components/modals/executions/schedule.tsx | 3 +-
.../components/modals/flows/create.tsx | 60 +++-
.../components/modals/runner/changeStatus.tsx | 5 +-
.../components/modals/runner/delete.tsx | 5 +-
.../components/modals/runner/edit.tsx | 5 +-
services/frontend/components/navbar.tsx | 17 +-
.../frontend/components/ui/animatedcard.tsx | 75 ++++
.../frontend/components/ui/integrations.tsx | 183 ++++++++++
services/frontend/components/ui/marquee.tsx | 52 +++
services/frontend/components/ui/usemouse.tsx | 67 ++++
.../frontend/lib/fetch/alert/DELETE/alert.ts | 69 ++++
.../frontend/lib/fetch/alert/POST/send.ts | 46 +++
services/frontend/lib/fetch/alert/alert.ts | 71 ++++
services/frontend/lib/fetch/alert/alerts.ts | 69 ++++
.../lib/fetch/flow/POST/CreateFlow.ts | 2 +
.../frontend/lib/fetch/flow/PUT/UpdateFlow.ts | 6 +
services/frontend/lib/swr/hooks/flows.ts | 16 +
services/frontend/tailwind.config.ts | 10 +
58 files changed, 2850 insertions(+), 193 deletions(-)
create mode 100644 services/backend/functions/encryption/alert_payload.go
create mode 100644 services/backend/handlers/alerts/create.go
create mode 100644 services/backend/handlers/alerts/delete.go
create mode 100644 services/backend/handlers/alerts/get_alert.go
create mode 100644 services/backend/handlers/alerts/get_alerts.go
create mode 100644 services/backend/handlers/alerts/get_grouped_alerts.go
create mode 100644 services/backend/handlers/alerts/update.go
create mode 100644 services/backend/handlers/flows/delete_alerts.go
create mode 100644 services/backend/handlers/flows/get_alerts.go
create mode 100644 services/backend/router/alerts.go
create mode 100644 services/frontend/components/alerts/heading.tsx
create mode 100644 services/frontend/components/alerts/list.tsx
create mode 100644 services/frontend/components/modals/alerts/delete.tsx
create mode 100644 services/frontend/components/modals/alerts/details.tsx
create mode 100644 services/frontend/components/modals/alerts/simulate.tsx
create mode 100644 services/frontend/components/ui/animatedcard.tsx
create mode 100644 services/frontend/components/ui/integrations.tsx
create mode 100644 services/frontend/components/ui/marquee.tsx
create mode 100644 services/frontend/components/ui/usemouse.tsx
create mode 100644 services/frontend/lib/fetch/alert/DELETE/alert.ts
create mode 100644 services/frontend/lib/fetch/alert/POST/send.ts
create mode 100644 services/frontend/lib/fetch/alert/alert.ts
create mode 100644 services/frontend/lib/fetch/alert/alerts.ts
diff --git a/services/backend/functions/background_checks/checkForFlowActionUpdates.go b/services/backend/functions/background_checks/checkForFlowActionUpdates.go
index 598b5376..0b12c6a3 100644
--- a/services/backend/functions/background_checks/checkForFlowActionUpdates.go
+++ b/services/backend/functions/background_checks/checkForFlowActionUpdates.go
@@ -7,7 +7,6 @@ import (
"github.com/Masterminds/semver"
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
"github.com/mohae/deepcopy" // Import for deep copy
log "github.com/sirupsen/logrus"
@@ -81,7 +80,7 @@ func updateFlowActions(flow *models.Flows, runners []models.Runners, project mod
if action.UpdateAvailable {
action.UpdateAvailable = false
action.UpdateVersion = ""
- action.UpdatedAction = &shared_models.Action{}
+ action.UpdatedAction = &models.Action{}
flow.Actions[j] = action
}
} else {
@@ -92,14 +91,14 @@ func updateFlowActions(flow *models.Flows, runners []models.Runners, project mod
// Check for action updates in the failure pipelines
for i, failurePipeline := range flow.FailurePipelines {
- updatedPipeline := deepcopy.Copy(failurePipeline).(shared_models.FailurePipeline) // Deep copy the pipeline
+ updatedPipeline := deepcopy.Copy(failurePipeline).(models.FailurePipeline) // Deep copy the pipeline
for j, action := range updatedPipeline.Actions {
if len(runners) == 0 {
if action.UpdateAvailable {
action.UpdateAvailable = false
action.UpdateVersion = ""
- action.UpdatedAction = &shared_models.Action{}
+ action.UpdatedAction = &models.Action{}
updatedPipeline.Actions[j] = action
}
} else {
@@ -111,7 +110,7 @@ func updateFlowActions(flow *models.Flows, runners []models.Runners, project mod
}
}
-func updateActionIfNeeded(flow *models.Flows, action shared_models.Action, runners []models.Runners, project models.Projects, db *bun.DB) shared_models.Action {
+func updateActionIfNeeded(flow *models.Flows, action models.Action, runners []models.Runners, project models.Projects, db *bun.DB) models.Action {
for _, runner := range runners {
for _, plugin := range runner.Plugins {
if action.Plugin == strings.ToLower(plugin.Name) {
@@ -136,13 +135,13 @@ func updateActionIfNeeded(flow *models.Flows, action shared_models.Action, runne
return action
}
-func createUpdatedAction(flow *models.Flows, action shared_models.Action, plugin shared_models.Plugin, project models.Projects, db *bun.DB) shared_models.Action {
- updatedAction := deepcopy.Copy(action).(shared_models.Action) // Deep copy the action
+func createUpdatedAction(flow *models.Flows, action models.Action, plugin models.Plugin, project models.Projects, db *bun.DB) models.Action {
+ updatedAction := deepcopy.Copy(action).(models.Action) // Deep copy the action
updatedAction.UpdateAvailable = true
updatedAction.UpdateVersion = plugin.Version
// Create a deep copy of plugin.Action to avoid shared references
- updatedPluginAction := deepcopy.Copy(plugin.Action).(shared_models.Action)
+ updatedPluginAction := deepcopy.Copy(plugin.Action).(models.Action)
updatedPluginAction.Version = plugin.Version
updatedAction.UpdatedAction = &updatedPluginAction
diff --git a/services/backend/functions/background_checks/checkHangingExecutionSteps.go b/services/backend/functions/background_checks/checkHangingExecutionSteps.go
index d4d70062..9cfbe0c8 100644
--- a/services/backend/functions/background_checks/checkHangingExecutionSteps.go
+++ b/services/backend/functions/background_checks/checkHangingExecutionSteps.go
@@ -6,7 +6,6 @@ import (
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
log "github.com/sirupsen/logrus"
"github.com/uptrace/bun"
@@ -65,9 +64,9 @@ func checkHangingExecutionSteps(db *bun.DB) {
step.Status = "error"
step.FinishedAt = time.Now()
- step.Messages = append(step.Messages, shared_models.Message{
+ step.Messages = append(step.Messages, models.Message{
Title: "Automated Check",
- Lines: []shared_models.Line{
+ Lines: []models.Line{
{
Content: "Execution is already finished, marking step as error",
Color: "danger",
diff --git a/services/backend/functions/background_checks/checkHangingExecutions.go b/services/backend/functions/background_checks/checkHangingExecutions.go
index 8906869b..424dcd7f 100644
--- a/services/backend/functions/background_checks/checkHangingExecutions.go
+++ b/services/backend/functions/background_checks/checkHangingExecutions.go
@@ -6,7 +6,6 @@ import (
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
log "github.com/sirupsen/logrus"
"github.com/uptrace/bun"
@@ -47,16 +46,16 @@ func checkHangingExecutions(db *bun.DB) {
continue
}
- step := shared_models.ExecutionSteps{
+ step := models.ExecutionSteps{
ExecutionID: execution.ID.String(),
- Action: shared_models.Action{
+ Action: models.Action{
Name: "Automated Check",
Icon: "hugeicons:robotic",
},
- Messages: []shared_models.Message{
+ Messages: []models.Message{
{
Title: "Automated Check",
- Lines: []shared_models.Line{
+ Lines: []models.Line{
{
Content: "Last execution heartbeat was more than 15 seconds ago",
Color: "danger",
@@ -126,9 +125,9 @@ func checkHangingExecutions(db *bun.DB) {
step.Encrypted = true
}
- step.Messages = append(step.Messages, shared_models.Message{
+ step.Messages = append(step.Messages, models.Message{
Title: "Automated Check",
- Lines: []shared_models.Line{
+ Lines: []models.Line{
{
Content: "Execution was marked as error, step will be canceled",
Color: "danger",
diff --git a/services/backend/functions/background_checks/checkScheduledExecutions.go b/services/backend/functions/background_checks/checkScheduledExecutions.go
index 10597a16..67c36010 100644
--- a/services/backend/functions/background_checks/checkScheduledExecutions.go
+++ b/services/backend/functions/background_checks/checkScheduledExecutions.go
@@ -6,7 +6,6 @@ import (
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
log "github.com/sirupsen/logrus"
"github.com/uptrace/bun"
@@ -67,9 +66,9 @@ func checkScheduledExecutions(db *bun.DB) {
step.Encrypted = true
}
- step.Messages = append(step.Messages, shared_models.Message{
+ step.Messages = append(step.Messages, models.Message{
Title: "Scheduled",
- Lines: []shared_models.Line{
+ Lines: []models.Line{
{
Content: "Scheduled time reached. Execution is now starting.",
Color: "success",
@@ -96,16 +95,16 @@ func checkScheduledExecutions(db *bun.DB) {
}
// create execution step which tells that the execution is registerd and waiting for runner to pick it up
- step := shared_models.ExecutionSteps{
+ step := models.ExecutionSteps{
ExecutionID: execution.ID.String(),
- Action: shared_models.Action{
+ Action: models.Action{
Name: "Pick Up",
Icon: "hugeicons:rocket",
},
- Messages: []shared_models.Message{
+ Messages: []models.Message{
{
Title: "Pick Up",
- Lines: []shared_models.Line{
+ Lines: []models.Line{
{
Content: "Waiting for runner to pick it up",
Timestamp: time.Now(),
diff --git a/services/backend/functions/background_checks/scheduleFlowExecutions.go b/services/backend/functions/background_checks/scheduleFlowExecutions.go
index 38d517ee..0cb42d7d 100644
--- a/services/backend/functions/background_checks/scheduleFlowExecutions.go
+++ b/services/backend/functions/background_checks/scheduleFlowExecutions.go
@@ -10,7 +10,6 @@ import (
"github.com/uptrace/bun"
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
)
func scheduleFlowExecutions(db *bun.DB) {
@@ -99,16 +98,16 @@ func createExecution(currentTime time.Time, flow models.Flows, db *bun.DB, conte
}
// create execution step which tells that the execution is registerd and waiting for runner to pick it up
- step := shared_models.ExecutionSteps{
+ step := models.ExecutionSteps{
ExecutionID: execution.ID.String(),
- Action: shared_models.Action{
+ Action: models.Action{
Name: "Scheduled",
Icon: "hugeicons:time-schedule",
},
- Messages: []shared_models.Message{
+ Messages: []models.Message{
{
Title: "Scheduled",
- Lines: []shared_models.Line{
+ Lines: []models.Line{
{
Content: "Execution is registered and is waiting for the scheduled time to start",
Timestamp: time.Now(),
diff --git a/services/backend/functions/encryption/alert_payload.go b/services/backend/functions/encryption/alert_payload.go
new file mode 100644
index 00000000..72a19c4a
--- /dev/null
+++ b/services/backend/functions/encryption/alert_payload.go
@@ -0,0 +1,100 @@
+package encryption
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "encoding/hex"
+ "encoding/json"
+ "errors"
+ "io"
+
+ "github.com/uptrace/bun"
+)
+
+func EncryptPayload(payload json.RawMessage, projectID string, db *bun.DB) (json.RawMessage, error) {
+ // Validate that the input payload is valid JSON
+ var validationInterface interface{}
+ if err := json.Unmarshal(payload, &validationInterface); err != nil {
+ return nil, errors.New("input payload is not valid JSON: " + err.Error())
+ }
+
+ encryptionKey, err := getEncryptionKey(projectID, db)
+ if err != nil {
+ return nil, err
+ }
+
+ block, err := aes.NewCipher(encryptionKey)
+ if err != nil {
+ return nil, err
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, err
+ }
+
+ // Generate a nonce for GCM
+ nonce := make([]byte, gcm.NonceSize())
+ if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
+ return nil, err
+ }
+
+ // Encrypt the JSON value
+ ciphertext := gcm.Seal(nonce, nonce, payload, nil)
+
+ // Encode the ciphertext as hex to make it safe for database storage
+ hexEncoded := hex.EncodeToString(ciphertext)
+
+ return json.RawMessage(`"` + hexEncoded + `"`), nil
+}
+
+func DecryptPayload(payload json.RawMessage, projectID string, db *bun.DB) (json.RawMessage, error) {
+ encryptionKey, err := getEncryptionKey(projectID, db)
+ if err != nil {
+ return nil, err
+ }
+
+ block, err := aes.NewCipher(encryptionKey)
+ if err != nil {
+ return nil, err
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, err
+ }
+
+ // Decode the hex string from JSON string format
+ var hexString string
+ if err := json.Unmarshal(payload, &hexString); err != nil {
+ return nil, errors.New("failed to unmarshal JSON string: " + err.Error())
+ }
+
+ ciphertext, err := hex.DecodeString(hexString)
+ if err != nil {
+ return nil, errors.New("failed to decode hex string: " + err.Error())
+ }
+
+ if len(ciphertext) < gcm.NonceSize() {
+ return nil, errors.New("ciphertext too short")
+ }
+
+ // Extract the nonce and ciphertext
+ nonce := ciphertext[:gcm.NonceSize()]
+ ciphertext = ciphertext[gcm.NonceSize():]
+
+ // Decrypt the ciphertext
+ plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
+ if err != nil {
+ return nil, errors.New("failed to decrypt: " + err.Error())
+ }
+
+ // Validate that the decrypted data is valid JSON
+ var validationInterface interface{}
+ if err := json.Unmarshal(plaintext, &validationInterface); err != nil {
+ return nil, errors.New("decrypted payload is not valid JSON: " + err.Error())
+ }
+
+ return json.RawMessage(plaintext), nil
+}
diff --git a/services/backend/functions/encryption/old_encryption.go b/services/backend/functions/encryption/old_encryption.go
index c5f18d6d..fc2feff8 100644
--- a/services/backend/functions/encryption/old_encryption.go
+++ b/services/backend/functions/encryption/old_encryption.go
@@ -10,10 +10,10 @@ import (
"fmt"
"github.com/v1Flows/exFlow/services/backend/config"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
)
-func DecryptParams(actions []shared_models.Action, decryptPasswords bool) ([]shared_models.Action, error) {
+func DecryptParams(actions []models.Action, decryptPasswords bool) ([]models.Action, error) {
block, err := aes.NewCipher([]byte(config.Config.Encryption.Key))
if err != nil {
return nil, err
@@ -122,7 +122,7 @@ func DecryptParams(actions []shared_models.Action, decryptPasswords bool) ([]sha
return actions, nil
}
-func DecryptExecutionStepActionMessage(encryptedMessage []shared_models.Message) ([]shared_models.Message, error) {
+func DecryptExecutionStepActionMessage(encryptedMessage []models.Message) ([]models.Message, error) {
block, err := aes.NewCipher([]byte(config.Config.Encryption.Key))
if err != nil {
return nil, err
diff --git a/services/backend/functions/encryption/project_execution_messages.go b/services/backend/functions/encryption/project_execution_messages.go
index 1d1ba952..40cd6c57 100644
--- a/services/backend/functions/encryption/project_execution_messages.go
+++ b/services/backend/functions/encryption/project_execution_messages.go
@@ -9,11 +9,11 @@ import (
"io"
"github.com/uptrace/bun"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
)
// EncryptExecutionStepActionMessageWithProject encrypts execution step messages using project-specific encryption
-func EncryptExecutionStepActionMessageWithProject(messages []shared_models.Message, projectID string, db *bun.DB) ([]shared_models.Message, error) {
+func EncryptExecutionStepActionMessageWithProject(messages []models.Message, projectID string, db *bun.DB) ([]models.Message, error) {
encryptionKey, err := getEncryptionKey(projectID, db)
if err != nil {
return nil, err
@@ -50,7 +50,7 @@ func EncryptExecutionStepActionMessageWithProject(messages []shared_models.Messa
}
// DecryptExecutionStepActionMessageWithProject decrypts execution step messages using project-specific encryption
-func DecryptExecutionStepActionMessageWithProject(encryptedMessage []shared_models.Message, projectID string, db *bun.DB) ([]shared_models.Message, error) {
+func DecryptExecutionStepActionMessageWithProject(encryptedMessage []models.Message, projectID string, db *bun.DB) ([]models.Message, error) {
encryptionKey, err := getEncryptionKey(projectID, db)
if err != nil {
return nil, err
diff --git a/services/backend/functions/encryption/project_params.go b/services/backend/functions/encryption/project_params.go
index 877690bb..c1dfb2f1 100644
--- a/services/backend/functions/encryption/project_params.go
+++ b/services/backend/functions/encryption/project_params.go
@@ -14,7 +14,6 @@ import (
"github.com/uptrace/bun"
"github.com/v1Flows/exFlow/services/backend/config"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
)
// getEncryptionKey returns the appropriate encryption key for a project
@@ -59,7 +58,7 @@ func getEncryptionKey(projectID string, db *bun.DB) ([]byte, error) {
}
// EncryptParamsWithProject encrypts action params using project-specific encryption
-func EncryptParamsWithProject(actions []shared_models.Action, projectID string, db *bun.DB) ([]shared_models.Action, error) {
+func EncryptParamsWithProject(actions []models.Action, projectID string, db *bun.DB) ([]models.Action, error) {
encryptionKey, err := getEncryptionKey(projectID, db)
if err != nil {
return nil, err
@@ -149,7 +148,7 @@ func EncryptParamsWithProject(actions []shared_models.Action, projectID string,
}
// DecryptParamsWithProject decrypts action params using project-specific encryption
-func DecryptParamsWithProject(actions []shared_models.Action, projectID string, decryptPasswords bool, db *bun.DB) ([]shared_models.Action, error) {
+func DecryptParamsWithProject(actions []models.Action, projectID string, decryptPasswords bool, db *bun.DB) ([]models.Action, error) {
encryptionKey, err := getEncryptionKey(projectID, db)
if err != nil {
return nil, err
@@ -264,7 +263,7 @@ func DecryptParamsWithProject(actions []shared_models.Action, projectID string,
}
// EncryptParamWithProject encrypts a single param using project-specific encryption
-func EncryptParamWithProject(param shared_models.Params, projectID string, db *bun.DB) (shared_models.Params, error) {
+func EncryptParamWithProject(param models.Params, projectID string, db *bun.DB) (models.Params, error) {
encryptionKey, err := getEncryptionKey(projectID, db)
if err != nil {
return param, err
diff --git a/services/backend/functions/flow/startExecution.go b/services/backend/functions/flow/startExecution.go
index b7bb42cb..ec7c42db 100644
--- a/services/backend/functions/flow/startExecution.go
+++ b/services/backend/functions/flow/startExecution.go
@@ -2,6 +2,8 @@ package functions
import (
"context"
+ "database/sql"
+ "time"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
@@ -9,9 +11,30 @@ import (
"github.com/uptrace/bun"
)
-func PreStartExecution(flowID string, flow models.Flows, db *bun.DB) error {
+func PreStartExecution(flowID string, flow models.Flows, db *bun.DB, alert models.Alerts) error {
context := context.Background()
+ // check when the last alert came in which got executed
+ var lastAlert models.Alerts
+ count, err := db.NewSelect().Model(&lastAlert).Where("flow_id = ? AND id != ? AND execution_id != ''", flowID, alert.ID).Order("created_at DESC").Limit(1).ScanAndCount(context)
+ if err != nil && err != sql.ErrNoRows {
+ return err
+ }
+
+ if count > 0 {
+ // compare the difference between the last alert and the current alert to the flow alert threshold
+ if lastAlert.CreatedAt.Add(time.Duration(flow.AlertThreshold) * time.Minute).After(alert.CreatedAt) {
+ // set note on alert why it was not executed
+ alert.Note = "Alert was not executed because it came in too soon after the last alert"
+ _, err = db.NewUpdate().Model(&alert).Column("note").Where("id = ?", alert.ID).Exec(context)
+ if err != nil {
+ return err
+ }
+
+ return nil
+ }
+ }
+
var execution models.Executions
if flow.RunnerID != "" {
@@ -21,7 +44,16 @@ func PreStartExecution(flowID string, flow models.Flows, db *bun.DB) error {
execution.ID = uuid.New()
execution.FlowID = flowID
execution.Status = "pending"
- _, err := db.NewInsert().Model(&execution).Column("id", "flow_id", "status", "executed_at").Exec(context)
+ execution.AlertID = alert.ID.String()
+
+ _, err = db.NewInsert().Model(&execution).Column("id", "flow_id", "alert_id", "status", "executed_at").Exec(context)
+ if err != nil {
+ return err
+ }
+
+ // set execution id on alert
+ alert.ExecutionID = execution.ID.String()
+ _, err = db.NewUpdate().Model(&alert).Column("execution_id").Where("id = ?", alert.ID).Exec(context)
if err != nil {
return err
}
diff --git a/services/backend/handlers/alerts/create.go b/services/backend/handlers/alerts/create.go
new file mode 100644
index 00000000..f1f988dc
--- /dev/null
+++ b/services/backend/handlers/alerts/create.go
@@ -0,0 +1,104 @@
+package alerts
+
+import (
+ "errors"
+ "net/http"
+ "time"
+
+ "github.com/v1Flows/exFlow/services/backend/functions/encryption"
+ functions "github.com/v1Flows/exFlow/services/backend/functions/flow"
+ "github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
+ "github.com/v1Flows/exFlow/services/backend/functions/httperror"
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
+
+ "github.com/gin-gonic/gin"
+ "github.com/google/uuid"
+ _ "github.com/lib/pq"
+ "github.com/uptrace/bun"
+
+ log "github.com/sirupsen/logrus"
+)
+
+func CreateAlert(context *gin.Context, db *bun.DB) {
+ var alert models.Alerts
+ if err := context.ShouldBindJSON(&alert); err != nil {
+ httperror.StatusBadRequest(context, "Error parsing incoming data", err)
+ return
+ }
+
+ var flow models.Flows
+ flowCount, err := db.NewSelect().Model(&flow).Where("id = ?", alert.FlowID).ScanAndCount(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting flow data from db", err)
+ return
+ }
+ if flowCount == 0 {
+ httperror.StatusNotFound(context, "Error no flow found", err)
+ return
+ }
+
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting project data from db", err)
+ return
+ }
+
+ access, err := gatekeeper.CheckUserProjectAccess(flow.ProjectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking your user permissions on project", err)
+ return
+ }
+ if !access {
+ httperror.Unauthorized(context, "You are not allowed to view this alert", errors.New("unauthorized"))
+ return
+ }
+
+ alert.ID = uuid.New()
+ alert.CreatedAt = time.Now()
+
+ // encrypt payload if enabled
+ if project.EncryptionEnabled {
+ alert.Payload, err = encryption.EncryptPayload(alert.Payload, project.ID.String(), db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error encrypting payload", err)
+ return
+ }
+ alert.Encrypted = true
+ }
+
+ res, err := db.NewInsert().Model(&alert).ExcludeColumn("execution_id").Exec(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error creating alert on db", err)
+ return
+ }
+
+ // if the alert has a parent_id we need to update the parent alert updated_at time
+ if alert.ParentID != "" {
+ parentAlert := models.Alerts{}
+ parentAlert.UpdatedAt = time.Now()
+ if alert.Status == "resolved" {
+ parentAlert.Status = "resolved"
+ _, err := db.NewUpdate().Model(&parentAlert).Where("id = ?", alert.ParentID).Column("updated_at", "status").Exec(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error updating parent alert on db", err)
+ return
+ }
+ } else {
+ _, err := db.NewUpdate().Model(&parentAlert).Where("id = ?", alert.ParentID).Column("updated_at").Exec(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error updating parent alert on db", err)
+ return
+ }
+ }
+ }
+
+ err = functions.PreStartExecution(alert.FlowID, flow, db, alert)
+ if err != nil {
+ log.Error("Failed to start execution: " + err.Error())
+ httperror.InternalServerError(context, "Failed to start execution", err)
+ }
+
+ context.JSON(http.StatusCreated, gin.H{"result": "success", "response": res})
+}
diff --git a/services/backend/handlers/alerts/delete.go b/services/backend/handlers/alerts/delete.go
new file mode 100644
index 00000000..480fa131
--- /dev/null
+++ b/services/backend/handlers/alerts/delete.go
@@ -0,0 +1,60 @@
+package alerts
+
+import (
+ "errors"
+ "net/http"
+
+ "github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
+ "github.com/v1Flows/exFlow/services/backend/functions/httperror"
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
+
+ "github.com/gin-gonic/gin"
+ _ "github.com/lib/pq"
+ "github.com/uptrace/bun"
+)
+
+func Delete(context *gin.Context, db *bun.DB) {
+ alertID := context.Param("alertID")
+
+ // get flow_id from alert
+ var alert models.Alerts
+ err := db.NewSelect().Model(&alert).Where("id = ?", alertID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting alert data from db", err)
+ return
+ }
+
+ // get project_id from flow_id
+ var flow models.Flows
+ err = db.NewSelect().Model(&flow).Where("id = ?", alert.FlowID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting flow data from db", err)
+ return
+ }
+
+ // check the requestors role in project
+ canModify, err := gatekeeper.CheckRequestUserProjectModifyRole(flow.ProjectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking your user permissions on project", err)
+ return
+ }
+ if !canModify {
+ httperror.Unauthorized(context, "You are not allowed to delete this alert", errors.New("unauthorized"))
+ return
+ }
+
+ // delete all alerts which got this alert id as parent_id
+ _, err = db.NewDelete().Model((*models.Alerts)(nil)).Where("parent_id = ?", alertID).Exec(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error deleting alert on db", err)
+ return
+ }
+
+ _, err = db.NewDelete().Model((*models.Alerts)(nil)).Where("id = ?", alertID).Exec(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error deleting alert on db", err)
+ return
+ }
+
+ context.JSON(http.StatusOK, gin.H{"result": "success"})
+}
diff --git a/services/backend/handlers/alerts/get_alert.go b/services/backend/handlers/alerts/get_alert.go
new file mode 100644
index 00000000..6a045398
--- /dev/null
+++ b/services/backend/handlers/alerts/get_alert.go
@@ -0,0 +1,54 @@
+package alerts
+
+import (
+ "errors"
+ "net/http"
+
+ "github.com/v1Flows/exFlow/services/backend/functions/encryption"
+ "github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
+ "github.com/v1Flows/exFlow/services/backend/functions/httperror"
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
+
+ "github.com/gin-gonic/gin"
+ _ "github.com/lib/pq"
+ "github.com/uptrace/bun"
+)
+
+func GetSingle(context *gin.Context, db *bun.DB) {
+ alertID := context.Param("alertID")
+
+ var alert models.Alerts
+ err := db.NewSelect().Model(&alert).Where("id = ?", alertID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting alert data from db", err)
+ return
+ }
+
+ // get project_id from flow_id
+ var flow models.Flows
+ err = db.NewSelect().Model(&flow).Where("id = ?", alert.FlowID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting flow data from db", err)
+ return
+ }
+
+ access, err := gatekeeper.CheckUserProjectAccess(flow.ProjectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking your user permissions on project", err)
+ return
+ }
+ if !access {
+ httperror.Unauthorized(context, "You are not allowed to view this alert", errors.New("unauthorized"))
+ return
+ }
+
+ if alert.Encrypted {
+ alert.Payload, err = encryption.DecryptPayload(alert.Payload, flow.ProjectID, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error decrypting alert", err)
+ return
+ }
+ }
+
+ context.JSON(http.StatusOK, gin.H{"alert": alert})
+}
diff --git a/services/backend/handlers/alerts/get_alerts.go b/services/backend/handlers/alerts/get_alerts.go
new file mode 100644
index 00000000..892c7356
--- /dev/null
+++ b/services/backend/handlers/alerts/get_alerts.go
@@ -0,0 +1,57 @@
+package alerts
+
+import (
+ "net/http"
+
+ "github.com/google/uuid"
+ "github.com/v1Flows/exFlow/services/backend/functions/auth"
+ "github.com/v1Flows/exFlow/services/backend/functions/encryption"
+ "github.com/v1Flows/exFlow/services/backend/functions/httperror"
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
+
+ "github.com/gin-gonic/gin"
+ _ "github.com/lib/pq"
+ "github.com/uptrace/bun"
+)
+
+func GetMultiple(context *gin.Context, db *bun.DB) {
+ userID, err := auth.GetUserIDFromToken(context.GetHeader("Authorization"))
+ if err != nil {
+ httperror.InternalServerError(context, "Error receiving userID from token", err)
+ return
+ }
+
+ // get all flows where the user is a member
+ flows := make([]models.Flows, 0)
+ err = db.NewSelect().Model(&flows).Column("id").Where("project_id::uuid IN (SELECT project_id::uuid FROM project_members WHERE user_id = ? AND invite_pending = false)", userID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting flows from db", err)
+ return
+ }
+
+ alerts := make([]models.Alerts, 0)
+
+ // get all alerts for each flow
+ flowIDs := make([]uuid.UUID, len(flows))
+ for i, flow := range flows {
+ flowIDs[i] = flow.ID
+ }
+
+ err = db.NewSelect().Model(&alerts).Where("flow_id IN (?)", bun.In(flowIDs)).Order("created_at DESC").Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting alerts from db", err)
+ return
+ }
+
+ for i := range alerts {
+ if alerts[i].Encrypted {
+ alerts[i].Payload, err = encryption.DecryptPayload(alerts[i].Payload, alerts[i].FlowID, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error decrypting alert", err)
+ return
+ }
+ }
+ }
+
+ context.JSON(http.StatusOK, gin.H{"alerts": alerts})
+}
diff --git a/services/backend/handlers/alerts/get_grouped_alerts.go b/services/backend/handlers/alerts/get_grouped_alerts.go
new file mode 100644
index 00000000..77631ca8
--- /dev/null
+++ b/services/backend/handlers/alerts/get_grouped_alerts.go
@@ -0,0 +1,66 @@
+package alerts
+
+import (
+ "errors"
+ "net/http"
+
+ "github.com/v1Flows/exFlow/services/backend/functions/encryption"
+ "github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
+ "github.com/v1Flows/exFlow/services/backend/functions/httperror"
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
+
+ "github.com/gin-gonic/gin"
+ _ "github.com/lib/pq"
+ "github.com/uptrace/bun"
+)
+
+func GetGrouped(context *gin.Context, db *bun.DB) {
+ var incomingRequest models.IncomingGroupedAlertsRequest
+ if err := context.ShouldBindJSON(&incomingRequest); err != nil {
+ httperror.StatusBadRequest(context, "Error parsing incoming data", err)
+ return
+ }
+
+ flow := models.Flows{}
+ err := db.NewSelect().Model(&flow).Where("id = ?", incomingRequest.FlowID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting flows from db", err)
+ return
+ }
+
+ access, err := gatekeeper.CheckUserProjectAccess(flow.ProjectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking your user permissions on project", err)
+ return
+ }
+ if !access {
+ httperror.Unauthorized(context, "You are not allowed to view this alert", errors.New("unauthorized"))
+ return
+ }
+
+ alerts := make([]models.Alerts, 0)
+
+ // check if grouped alerts are enabled
+ if flow.GroupAlerts {
+ err = db.NewSelect().Model(&alerts).Where("flow_id = ? AND group_key = ? AND status != 'resolved' AND parent_id = ''", incomingRequest.FlowID, incomingRequest.GroupAlertsIdentifier).Order("created_at ASC").Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting alerts from db", err)
+ return
+ }
+ } else {
+ httperror.StatusNotFound(context, "Grouped alerts are not enabled", nil)
+ return
+ }
+
+ for i := range alerts {
+ if alerts[i].Encrypted {
+ alerts[i].Payload, err = encryption.DecryptPayload(alerts[i].Payload, flow.ProjectID, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error decrypting alert", err)
+ return
+ }
+ }
+ }
+
+ context.JSON(http.StatusOK, gin.H{"alerts": alerts})
+}
diff --git a/services/backend/handlers/alerts/update.go b/services/backend/handlers/alerts/update.go
new file mode 100644
index 00000000..dc159043
--- /dev/null
+++ b/services/backend/handlers/alerts/update.go
@@ -0,0 +1,101 @@
+package alerts
+
+import (
+ "errors"
+ "net/http"
+ "time"
+
+ "github.com/v1Flows/exFlow/services/backend/functions/encryption"
+ "github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
+ "github.com/v1Flows/exFlow/services/backend/functions/httperror"
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
+
+ "github.com/gin-gonic/gin"
+ _ "github.com/lib/pq"
+ "github.com/uptrace/bun"
+)
+
+func Update(context *gin.Context, db *bun.DB) {
+ alertID := context.Param("alertID")
+
+ var alert models.Alerts
+ if err := context.ShouldBindJSON(&alert); err != nil {
+ httperror.StatusBadRequest(context, "Error parsing incoming data", err)
+ return
+ }
+
+ var alertDB models.Alerts
+ err := db.NewSelect().Model(&alertDB).Where("id = ?", alertID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting alert data from db", err)
+ return
+ }
+
+ // get project_id from flow_id
+ var flow models.Flows
+ err = db.NewSelect().Model(&flow).Where("id = ?", alertDB.FlowID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting flow data from db", err)
+ return
+ }
+
+ // get project data
+ var project models.Projects
+ err = db.NewSelect().Model(&project).Where("id = ?", flow.ProjectID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting project data from db", err)
+ return
+ }
+
+ access, err := gatekeeper.CheckUserProjectAccess(flow.ProjectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking your user permissions on project", err)
+ return
+ }
+ if !access {
+ httperror.Unauthorized(context, "You are not allowed to view this alert", errors.New("unauthorized"))
+ return
+ }
+
+ alert.UpdatedAt = time.Now()
+ columns := []string{}
+ if alert.Name != "" {
+ columns = append(columns, "name")
+ }
+ if alert.FlowID != "" {
+ columns = append(columns, "flow_id")
+ }
+ if len(alert.Payload) != 0 {
+ columns = append(columns, "payload")
+
+ if project.EncryptionEnabled {
+ alert.Payload, err = encryption.EncryptPayload(alert.Payload, project.ID.String(), db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error encrypting payload", err)
+ return
+ }
+ alert.Encrypted = true
+ columns = append(columns, "encrypted")
+ }
+ }
+ if alert.Status != alertDB.Status {
+ columns = append(columns, "status")
+ }
+ if alert.ResolvedAt != alertDB.ResolvedAt {
+ columns = append(columns, "resolved_at")
+ }
+ if alert.ParentID != alertDB.ParentID {
+ columns = append(columns, "parent_id")
+ }
+ if alert.UpdatedAt != alertDB.UpdatedAt {
+ columns = append(columns, "updated_at")
+ }
+
+ _, err = db.NewUpdate().Model(&alert).Column(columns...).Where("id = ?", alertID).Exec(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error updating alert on db", err)
+ return
+ }
+
+ context.JSON(http.StatusOK, gin.H{"alert": alert})
+}
diff --git a/services/backend/handlers/executions/schedule.go b/services/backend/handlers/executions/schedule.go
index 62853743..8778ca77 100644
--- a/services/backend/handlers/executions/schedule.go
+++ b/services/backend/handlers/executions/schedule.go
@@ -8,7 +8,6 @@ import (
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
"github.com/gin-gonic/gin"
"github.com/uptrace/bun"
@@ -43,16 +42,16 @@ func ScheduleExecution(context *gin.Context, db *bun.DB) {
}
// create execution step which tells that the execution is registerd and waiting for runner to pick it up
- step := shared_models.ExecutionSteps{
+ step := models.ExecutionSteps{
ExecutionID: execution.ID.String(),
- Action: shared_models.Action{
+ Action: models.Action{
Name: "Scheduled",
Icon: "hugeicons:time-schedule",
},
- Messages: []shared_models.Message{
+ Messages: []models.Message{
{
Title: "Scheduled",
- Lines: []shared_models.Line{
+ Lines: []models.Line{
{
Content: "Execution is registered and is waiting for the scheduled time to start",
Timestamp: time.Now(),
diff --git a/services/backend/handlers/executions/update_step.go b/services/backend/handlers/executions/update_step.go
index 486883bb..f841594e 100644
--- a/services/backend/handlers/executions/update_step.go
+++ b/services/backend/handlers/executions/update_step.go
@@ -7,7 +7,6 @@ import (
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
"github.com/gin-gonic/gin"
"github.com/uptrace/bun"
@@ -16,7 +15,7 @@ import (
func UpdateStep(context *gin.Context, db *bun.DB) {
stepID := context.Param("stepID")
- var step shared_models.ExecutionSteps
+ var step models.ExecutionSteps
if err := context.ShouldBindJSON(&step); err != nil {
httperror.StatusBadRequest(context, "Error parsing incoming data", err)
log.Error("Error parsing incoming data", err)
@@ -24,7 +23,7 @@ func UpdateStep(context *gin.Context, db *bun.DB) {
}
// get current action messages
- var dbStep shared_models.ExecutionSteps
+ var dbStep models.ExecutionSteps
err := db.NewSelect().Model(&dbStep).Where("id = ?", stepID).Scan(context)
if err != nil {
httperror.InternalServerError(context, "Error collecting current step messages from db", err)
diff --git a/services/backend/handlers/flows/add_failure_pipeline_actions.go b/services/backend/handlers/flows/add_failure_pipeline_actions.go
index 8cddf496..448ef7f6 100644
--- a/services/backend/handlers/flows/add_failure_pipeline_actions.go
+++ b/services/backend/handlers/flows/add_failure_pipeline_actions.go
@@ -11,7 +11,6 @@ import (
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
functions_project "github.com/v1Flows/exFlow/services/backend/functions/project"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
"github.com/gin-gonic/gin"
_ "github.com/lib/pq"
@@ -22,7 +21,7 @@ func AddFlowFailurePipelineActions(context *gin.Context, db *bun.DB) {
flowID := context.Param("flowID")
failurePipelineID := context.Param("failurePipelineID")
- var failurePipeline shared_models.FailurePipeline
+ var failurePipeline models.FailurePipeline
if err := context.ShouldBindJSON(&failurePipeline); err != nil {
httperror.StatusBadRequest(context, "Error parsing incoming data", err)
return
diff --git a/services/backend/handlers/flows/delete_alerts.go b/services/backend/handlers/flows/delete_alerts.go
new file mode 100644
index 00000000..6cf4a6f9
--- /dev/null
+++ b/services/backend/handlers/flows/delete_alerts.go
@@ -0,0 +1,64 @@
+package flows
+
+import (
+ "errors"
+ "net/http"
+
+ "github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
+ "github.com/v1Flows/exFlow/services/backend/functions/httperror"
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
+
+ "github.com/gin-gonic/gin"
+ _ "github.com/lib/pq"
+ "github.com/uptrace/bun"
+)
+
+func DeleteAlert(context *gin.Context, db *bun.DB) {
+ alertID := context.Param("alertID")
+
+ // get alert data from db
+ var alert models.Alerts
+ err := db.NewSelect().Model(&alert).Where("id = ?", alertID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting alert data from db", err)
+ return
+ }
+
+ // get flow data
+ var flow models.Flows
+ err = db.NewSelect().Model(&flow).Where("id = ?", alert.FlowID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting flow data from db", err)
+ return
+ }
+
+ // check if user has access to project
+ access, err := gatekeeper.CheckUserProjectAccess(flow.ProjectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking for flow access", err)
+ return
+ }
+ if !access {
+ httperror.Unauthorized(context, "You do not have access to this flow", errors.New("you do not have access to this flow"))
+ return
+ }
+
+ // check the requestors role in project
+ canModify, err := gatekeeper.CheckRequestUserProjectModifyRole(flow.ProjectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking your user permissions on flow", err)
+ return
+ }
+ if !canModify {
+ httperror.Unauthorized(context, "You are not allowed to make modifications on this flow", errors.New("unauthorized"))
+ return
+ }
+
+ _, err = db.NewDelete().Model((*models.Alerts)(nil)).Where("id = ?", alertID).Exec(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error deleting alert from db", err)
+ return
+ }
+
+ context.JSON(http.StatusOK, gin.H{"result": "success"})
+}
diff --git a/services/backend/handlers/flows/get_alerts.go b/services/backend/handlers/flows/get_alerts.go
new file mode 100644
index 00000000..017c2126
--- /dev/null
+++ b/services/backend/handlers/flows/get_alerts.go
@@ -0,0 +1,57 @@
+package flows
+
+import (
+ "errors"
+ "net/http"
+
+ "github.com/v1Flows/exFlow/services/backend/functions/encryption"
+ "github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
+ "github.com/v1Flows/exFlow/services/backend/functions/httperror"
+ "github.com/v1Flows/exFlow/services/backend/pkg/models"
+
+ "github.com/gin-gonic/gin"
+ _ "github.com/lib/pq"
+ "github.com/uptrace/bun"
+)
+
+func GetFlowAlerts(context *gin.Context, db *bun.DB) {
+ flowID := context.Param("flowID")
+
+ // get flow
+ var flow models.Flows
+ err := db.NewSelect().Model(&flow).Where("id = ?", flowID).Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting flow data from db", err)
+ return
+ }
+
+ // check if user has access to project
+ access, err := gatekeeper.CheckUserProjectAccess(flow.ProjectID, context, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error checking for flow access", err)
+ return
+ }
+ if !access {
+ httperror.Unauthorized(context, "You do not have access to this flow", errors.New("you do not have access to this flow"))
+ return
+ }
+
+ alerts := make([]models.Alerts, 0)
+ err = db.NewSelect().Model(&alerts).Where("flow_id = ?", flowID).Order("created_at DESC").Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting flow alerts from db", err)
+ return
+ }
+
+ for i := range alerts {
+ if alerts[i].Encrypted {
+ alerts[i].Payload, err = encryption.DecryptPayload(alerts[i].Payload, flow.ProjectID, db)
+ if err != nil {
+ httperror.InternalServerError(context, "Error decrypting payload", err)
+ return
+ }
+ }
+ }
+
+ context.JSON(http.StatusOK, gin.H{"alerts": alerts})
+}
diff --git a/services/backend/handlers/flows/start_execution.go b/services/backend/handlers/flows/start_execution.go
index ff41e9d4..2c1db034 100644
--- a/services/backend/handlers/flows/start_execution.go
+++ b/services/backend/handlers/flows/start_execution.go
@@ -10,7 +10,6 @@ import (
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
"github.com/gin-gonic/gin"
"github.com/uptrace/bun"
@@ -59,16 +58,16 @@ func StartExecution(context *gin.Context, db *bun.DB) {
}
// create execution step which tells that the execution is registerd and waiting for runner to pick it up
- step := shared_models.ExecutionSteps{
+ step := models.ExecutionSteps{
ExecutionID: execution.ID.String(),
- Action: shared_models.Action{
+ Action: models.Action{
Name: "Pick Up",
Icon: "hugeicons:rocket",
},
- Messages: []shared_models.Message{
+ Messages: []models.Message{
{
Title: "Pick Up",
- Lines: []shared_models.Line{
+ Lines: []models.Line{
{
Content: "Execution is registered and waiting for runner to pick it up",
Timestamp: time.Now(),
diff --git a/services/backend/handlers/flows/update.go b/services/backend/handlers/flows/update.go
index 99e5faf5..6ac62580 100644
--- a/services/backend/handlers/flows/update.go
+++ b/services/backend/handlers/flows/update.go
@@ -56,6 +56,9 @@ func UpdateFlow(context *gin.Context, db *bun.DB) {
flow.UpdatedAt = time.Now()
columns := []string{}
+ if flow.Type != "" {
+ columns = append(columns, "type")
+ }
if flow.Name != "" {
columns = append(columns, "name")
}
@@ -77,6 +80,18 @@ func UpdateFlow(context *gin.Context, db *bun.DB) {
if flow.ScheduleEveryUnit != flowDB.ScheduleEveryUnit {
columns = append(columns, "schedule_every_unit")
}
+ if flow.GroupAlerts != flowDB.GroupAlerts {
+ columns = append(columns, "group_alerts")
+ }
+ if flow.GroupAlertsIdentifier != flowDB.GroupAlertsIdentifier {
+ columns = append(columns, "group_alerts_identifier")
+ }
+ if flow.AlertThreshold != flowDB.AlertThreshold {
+ columns = append(columns, "alert_threshold")
+ }
+ if flow.ScheduleEveryUnit != flowDB.ScheduleEveryUnit {
+ columns = append(columns, "schedule_every_unit")
+ }
columns = append(columns, "exec_parallel")
columns = append(columns, "failure_pipeline_id")
columns = append(columns, "updated_at")
diff --git a/services/backend/handlers/flows/update_failure_pipeline_actions.go b/services/backend/handlers/flows/update_failure_pipeline_actions.go
index 979db7fe..cbb0b38a 100644
--- a/services/backend/handlers/flows/update_failure_pipeline_actions.go
+++ b/services/backend/handlers/flows/update_failure_pipeline_actions.go
@@ -9,7 +9,6 @@ import (
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
functions_project "github.com/v1Flows/exFlow/services/backend/functions/project"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
"github.com/gin-gonic/gin"
_ "github.com/lib/pq"
@@ -21,7 +20,7 @@ func UpdateFlowFailurePipelineActions(context *gin.Context, db *bun.DB) {
flowID := context.Param("flowID")
failurePipelineID := context.Param("failurePipelineID")
- var failurePipeline shared_models.FailurePipeline
+ var failurePipeline models.FailurePipeline
if err := context.ShouldBindJSON(&failurePipeline); err != nil {
httperror.StatusBadRequest(context, "Error parsing incoming data", err)
return
diff --git a/services/backend/handlers/runners/register.go b/services/backend/handlers/runners/register.go
index 0b40e9de..e8896680 100644
--- a/services/backend/handlers/runners/register.go
+++ b/services/backend/handlers/runners/register.go
@@ -11,7 +11,6 @@ import (
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
functions_runner "github.com/v1Flows/exFlow/services/backend/functions/runner"
"github.com/v1Flows/exFlow/services/backend/pkg/models"
- shared_models "github.com/v1Flows/shared-library/pkg/models"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
@@ -43,7 +42,7 @@ func RegisterRunner(context *gin.Context, db *bun.DB) {
}
var runner models.Runners
- var autoRunner shared_models.IncomingAutoRunners
+ var autoRunner models.IncomingAutoRunners
if runnerType == "project_auto_runner" {
if err := context.ShouldBindJSON(&autoRunner); err != nil {
diff --git a/services/backend/router/alerts.go b/services/backend/router/alerts.go
new file mode 100644
index 00000000..fb8fdf1d
--- /dev/null
+++ b/services/backend/router/alerts.go
@@ -0,0 +1,34 @@
+package router
+
+import (
+ "github.com/v1Flows/exFlow/services/backend/handlers/alerts"
+ "github.com/v1Flows/exFlow/services/backend/middlewares"
+
+ "github.com/gin-gonic/gin"
+ "github.com/uptrace/bun"
+)
+
+func Alerts(router *gin.RouterGroup, db *bun.DB) {
+ alert := router.Group("/alerts").Use(middlewares.Mixed(db))
+ {
+ alert.GET("/", func(c *gin.Context) {
+ alerts.GetMultiple(c, db)
+ })
+ alert.GET("/grouped", func(c *gin.Context) {
+ alerts.GetGrouped(c, db)
+ })
+ alert.GET("/:alertID", func(c *gin.Context) {
+ alerts.GetSingle(c, db)
+ })
+
+ alert.POST("/", func(c *gin.Context) {
+ alerts.CreateAlert(c, db)
+ })
+ alert.PUT("/:alertID", func(c *gin.Context) {
+ alerts.Update(c, db)
+ })
+ alert.DELETE("/:alertID", func(c *gin.Context) {
+ alerts.Delete(c, db)
+ })
+ }
+}
diff --git a/services/backend/router/flows.go b/services/backend/router/flows.go
index 3cdb85d1..05d8b67f 100644
--- a/services/backend/router/flows.go
+++ b/services/backend/router/flows.go
@@ -75,6 +75,11 @@ func Flows(router *gin.RouterGroup, db *bun.DB) {
flows.DeleteFlowFailurePipelineAction(c, db)
})
+ // alerts
+ flow.GET("/:flowID/alerts", func(c *gin.Context) {
+ flows.GetFlowAlerts(c, db)
+ })
+
// executions
flow.GET("/:flowID/executions", func(c *gin.Context) {
flows.GetFlowExecutions(c, db)
diff --git a/services/backend/router/main.go b/services/backend/router/main.go
index 0ca47b67..c2311c67 100644
--- a/services/backend/router/main.go
+++ b/services/backend/router/main.go
@@ -32,6 +32,7 @@ func StartRouter(db *bun.DB, port int) {
Executions(v1, db)
Flows(v1, db)
Page(v1, db)
+ Alerts(v1, db)
Projects(v1, db)
Runners(v1, db)
Token(v1, db)
diff --git a/services/frontend/components/alerts/heading.tsx b/services/frontend/components/alerts/heading.tsx
new file mode 100644
index 00000000..be759dab
--- /dev/null
+++ b/services/frontend/components/alerts/heading.tsx
@@ -0,0 +1,84 @@
+import { Card, CardBody, Spacer } from "@heroui/react";
+import { Icon } from "@iconify/react";
+import NumberFlow from "@number-flow/react";
+
+export default function AlertsHeading({ alerts }: any) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ alert.status === "firing")
+ .length
+ }
+ />
+
+
Firing
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ alert.status === "resolved",
+ ).length
+ }
+ />
+
+
Resolved
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/services/frontend/components/alerts/list.tsx b/services/frontend/components/alerts/list.tsx
new file mode 100644
index 00000000..64e100d3
--- /dev/null
+++ b/services/frontend/components/alerts/list.tsx
@@ -0,0 +1,280 @@
+"use client";
+
+import {
+ Accordion,
+ AccordionItem,
+ Card,
+ CardBody,
+ Chip,
+ Listbox,
+ ListboxItem,
+ Pagination,
+ ScrollShadow,
+ Spacer,
+ useDisclosure,
+} from "@heroui/react";
+import { Icon } from "@iconify/react";
+import { useMemo, useState } from "react";
+import ReactTimeago from "react-timeago";
+
+import { IconWrapper } from "@/lib/IconWrapper";
+import AlertDrawer from "@/components/modals/alerts/details";
+
+export default function AlertsList({
+ compactMode,
+ alerts,
+ runners,
+ flows,
+ maxAlerts,
+ canEdit,
+ showDelete,
+ showFlowChip,
+}: {
+ compactMode: boolean;
+ maxAlerts: number;
+ alerts: any;
+ runners: any;
+ flows?: any;
+ canEdit?: boolean;
+ showDelete?: boolean;
+ showFlowChip?: boolean;
+}) {
+ const alertDrawer = useDisclosure();
+
+ const [targetAlert, setTargetAlert] = useState(null);
+
+ // pagination
+ const [page, setPage] = useState(1);
+ const pages = Math.ceil(
+ alerts.filter((alert: any) => !alert.parent_id).length / maxAlerts,
+ );
+ const items = useMemo(() => {
+ const filteredAlerts = alerts.filter((alert: any) => !alert.parent_id);
+ const start = (page - 1) * maxAlerts;
+ const end = start + maxAlerts;
+
+ return filteredAlerts.slice(start, end);
+ }, [page, alerts]);
+
+ return (
+
+
+ {items.map((alert: any) => (
+
{
+ setTargetAlert(alert);
+ alertDrawer.onOpenChange();
+ }}
+ >
+
+
+
+
+
+
+
+
{alert.name || "N/A"}
+
+ {alert.status || "N/A"}
+
+
+
+
+
+ {showFlowChip && (
+
+ Flow:{" "}
+ {
+ flows.filter((f: any) => f.id === alert.flow_id)[0]
+ ?.name
+ }
+
+ )}
+ {alert.execution_id !== "" && (
+
+ Executed
+
+ )}
+ {alerts.filter((a: any) => a.parent_id === alert.id).length >
+ 0 && (
+ <>
+
+ Parent Alert
+
+
+ {
+ alerts.filter((a: any) => a.parent_id === alert.id)
+ .length
+ }{" "}
+ Sub Alert/s
+
+ >
+ )}
+ {alert.updated_at !== "0001-01-01T00:00:00Z" && (
+
+
+ Last Update:
+
+
+ )}
+
+
+ Created:
+
+
+
+
+
+
+
+ {alerts.filter((a: any) => a.parent_id === alert.id).length >
+ 0 && (
+
+
+
+
+ {alerts.map((a: any) => {
+ if (a.parent_id === alert.id) {
+ return (
+
+
+
+ }
+ textValue={a.name}
+ onPress={() => {
+ setTargetAlert(a);
+ alertDrawer.onOpenChange();
+ }}
+ >
+
+
{a.name}
+
+
+ {a.status || "N/A"}
+
+
+
+
+
+ {new Date(a.created_at).getTime() ===
+ Math.max(
+ ...alerts
+ .filter(
+ (alert: any) =>
+ alert.parent_id === a.parent_id,
+ )
+ .map((alert: any) =>
+ new Date(
+ alert.created_at,
+ ).getTime(),
+ ),
+ ) && (
+
+ Latest
+
+ )}
+ {a.execution_id !== "" && (
+
+ Executed
+
+ )}
+
+
+
+
+ );
+ }
+ })}
+
+
+
+
+ )}
+
+
+ ))}
+
+ {!compactMode && (
+
+ )}
+
+
+ );
+}
diff --git a/services/frontend/components/flows/flow/actions.tsx b/services/frontend/components/flows/flow/actions.tsx
index b2f33b6a..1d5ad5a2 100644
--- a/services/frontend/components/flows/flow/actions.tsx
+++ b/services/frontend/components/flows/flow/actions.tsx
@@ -34,6 +34,7 @@ import CopyActionModal from "@/components/modals/actions/copy";
import UpgradeActionModal from "@/components/modals/actions/upgrade";
import CopyActionToDifferentFlowModal from "@/components/modals/actions/transferCopy";
import FlowActionDetails from "@/components/modals/actions/details";
+import { Integrations } from "@/components/ui/integrations";
export default function Actions({
projects,
@@ -402,6 +403,11 @@ export default function Actions({
+ {actions.length === 0 && (
+
+
+
+ )}
-
+
@@ -82,6 +82,21 @@ export default function FlowDetails({
+
diff --git a/services/frontend/components/flows/flow/failure-pipelines.tsx b/services/frontend/components/flows/flow/failure-pipelines.tsx
index 6636c6d0..82b6c18b 100644
--- a/services/frontend/components/flows/flow/failure-pipelines.tsx
+++ b/services/frontend/components/flows/flow/failure-pipelines.tsx
@@ -19,7 +19,6 @@ import {
DropdownItem,
DropdownMenu,
DropdownTrigger,
- ScrollShadow,
Spacer,
Tab,
Tabs,
@@ -591,25 +590,23 @@ export default function FlowFailurePipelines({
-
- handleDragEndPipeline(pipeline, event)}
+ handleDragEndPipeline(pipeline, event)}
+ >
+
-
-
- {pipeline.actions !== null &&
- pipeline.actions.length > 0 &&
- pipeline.actions.map((action: any) => (
-
- ))}
-
-
-
-
+
+ {pipeline.actions !== null &&
+ pipeline.actions.length > 0 &&
+ pipeline.actions.map((action: any) => (
+
+ ))}
+
+
+
))}
diff --git a/services/frontend/components/flows/flow/heading.tsx b/services/frontend/components/flows/flow/heading.tsx
index 393a14f5..bef3bb2c 100644
--- a/services/frontend/components/flows/flow/heading.tsx
+++ b/services/frontend/components/flows/flow/heading.tsx
@@ -8,6 +8,7 @@ import EditFlowModal from "@/components/modals/flows/edit";
import canEditProject from "@/lib/functions/canEditProject";
import { startExecution } from "@/lib/swr/api/executions";
import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
+import SimulateAlertModal from "@/components/modals/alerts/simulate";
export default function FlowHeading({
flow,
@@ -26,6 +27,7 @@ export default function FlowHeading({
}) {
const editFlowModal = useDisclosure();
const scheduleExecutionModal = useDisclosure();
+ const simulateAlertModal = useDisclosure();
const { refreshAllExecutionCaches } = useRefreshCache();
const handleExecuteFlow = async () => {
@@ -56,31 +58,52 @@ export default function FlowHeading({
-
}
- variant="flat"
- onPress={() => {
- scheduleExecutionModal.onOpen();
- }}
- >
- Schedule
-
-
}
- variant="solid"
- onPress={handleExecuteFlow}
- >
- Execute
-
+ {flow.type === "alert" ? (
+
}
+ variant="flat"
+ onPress={() => {
+ simulateAlertModal.onOpen();
+ }}
+ >
+ Simulate Alert
+
+ ) : (
+ <>
+
+ }
+ variant="flat"
+ onPress={() => {
+ scheduleExecutionModal.onOpen();
+ }}
+ >
+ Schedule
+
+
}
+ variant="solid"
+ onPress={handleExecuteFlow}
+ >
+ Execute
+
+ >
+ )}
- }
- variant="flat"
- onPress={() => {
- scheduleExecutionModal.onOpen();
- }}
- />
- }
- variant="solid"
- onPress={handleExecuteFlow}
- />
-
- }
- variant="flat"
- onPress={() => {
- editFlowModal.onOpen();
- }}
- />
+ {flow.type === "alert" ? (
+ }
+ variant="flat"
+ onPress={() => {
+ scheduleExecutionModal.onOpen();
+ }}
+ />
+ ) : (
+ <>
+
+ }
+ variant="flat"
+ onPress={() => {
+ scheduleExecutionModal.onOpen();
+ }}
+ />
+ }
+ variant="solid"
+ onPress={handleExecuteFlow}
+ />
+
+
+ }
+ variant="flat"
+ onPress={() => {
+ editFlowModal.onOpen();
+ }}
+ />
+ >
+ )}
+
Executions
-
-
-
-
-
-
Schedule Every
-
- Schedule the flow to run every X minutes/hours/days.{" "}
-
- The system will always schedule two executions at the
- time. The second one will be scheduled base on the
- scheduled time of the first one.
-
-
- Enter 0 to disable the schedule.
-
-
+
+
+
+
+
Schedule Every
+
+ Schedule the flow to run every X minutes/hours/days.{" "}
+
+ The system will always schedule two executions at the
+ time. The second one will be scheduled base on the
+ scheduled time of the first one.
+
+
+ Enter 0 to disable the schedule.
+
+
+
+
+
+ {
+ setScheduleEveryUnit(e.currentKey);
+ }}
+ >
+ Minutes
+ Hours
+ Days
+ Weeks
+
+
+
+
+
+
+
+
+ {flow.type === "alert" && (
+
+
+ Alerting
+
+
+
+
+
+
Group Alerts
+
+ Group Alerts by an identifier. This will set the
+ parentID of the alert to the first alert of the group.
+ The identifier can be set by another setting
+
+
+
+
+
-
-
+
+
+
+
+
+
+
Group Identifier
+
+ Enter a unique identifier for the group of alerts. To
+ access payload data use{" "}
+
+ payload.
+ {" "}
+ as prefix
+
+
+
-
{
- setScheduleEveryUnit(e.currentKey);
- }}
- >
- Minutes
- Hours
- Days
- Weeks
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
Threshold
+
+ If an alert is resolved and reoccurs after which
+ threshold should a new execution be accepted?
+
+
+
+ minutes
+ }
+ isDisabled={
+ (!canEdit || flow.disabled) && user.role !== "admin"
+ }
+ minValue={0}
+ placeholder="Enter a number"
+ variant="bordered"
+ onValueChange={setAlertThreshold}
+ />
+
+
+
+
+
+
+
+ )}
+ {flow.type === "alert" && (
+
+
+ Alerts
+
+ }
+ >
+
+
+ )}
+
+
+
+ {(onClose) => (
+ <>
+
+
+
Are you sure?
+
+ You are about to delete the following alert which{" "}
+ cannot be undone
+
+
+
+
+ {error && (
+
+ )}
+
+
+ ID:
+ {alert.id}
+
+
+
+
+
+ Cancel
+
+
+ Delete
+
+
+ >
+ )}
+
+
+
+ );
+}
diff --git a/services/frontend/components/modals/alerts/details.tsx b/services/frontend/components/modals/alerts/details.tsx
new file mode 100644
index 00000000..f61336df
--- /dev/null
+++ b/services/frontend/components/modals/alerts/details.tsx
@@ -0,0 +1,334 @@
+import {
+ Drawer,
+ DrawerContent,
+ DrawerHeader,
+ DrawerBody,
+ DrawerFooter,
+ Button,
+ Chip,
+ Snippet,
+ Code,
+ Divider,
+ Listbox,
+ ListboxItem,
+} from "@heroui/react";
+import { useDisclosure, UseDisclosureReturn } from "@heroui/use-disclosure";
+import { Icon } from "@iconify/react";
+import { useRouter } from "next/navigation";
+import { useState } from "react";
+import ReactTimeago from "react-timeago";
+
+import { IconWrapper } from "@/lib/IconWrapper";
+
+import DeleteAlertModal from "./delete";
+
+export default function AlertDrawer({
+ alert,
+ runners,
+ flows,
+ disclosure,
+ canEdit,
+ showDelete,
+}: {
+ alert: any;
+ runners: any;
+ flows: any;
+ disclosure: UseDisclosureReturn;
+ canEdit?: boolean;
+ showDelete?: boolean;
+}) {
+ const { isOpen, onOpenChange } = disclosure;
+ const router = useRouter();
+
+ const [showPayload, setShowPayload] = useState(false);
+ const deleteAlertModal = useDisclosure();
+
+ const handleDelete = () => {
+ deleteAlertModal.onOpen();
+ onOpenChange();
+ };
+
+ return (
+ <>
+
+
+ {(onClose) => (
+ <>
+
+
+ {alert.name || "Untitled"}
+
+ {alert.status}
+
+
+ {alert.encrypted ? "Encrypted" : "Unencrypted"}
+
+
+
+
+
+
+
ID
+
+ {alert.id}
+
+
+
+ Plugin
+
+
{alert.plugin || "N/A"}
+
+
+ Runner
+
+
+ {runners.find((runner) => runner.id === alert.runner_id)
+ ?.name || "N/A"}
+
+
+
Flow
+
+ {flows.find((flow) => flow.id === alert.flow_id)?.name ||
+ "N/A"}
+
+
+
+ Group Ident
+
+
+ {alert.group_key || "N/A"}
+
+
+
+ Execution ID
+
+
+ {alert.execution_id || "N/A"}
+
+
+ {alert.parent_id && (
+ <>
+
+ Parent Alert
+
+
+ {alert.parent_id || "N/A"}
+
+ >
+ )}
+
+
+ Payload
+
+
setShowPayload(!showPayload)}
+ >
+ {showPayload ? "Hide" : "Show"} Payload
+
+
+
+ Created At
+
+
+
+
+
+
+ Updated At
+
+
+ {alert.updated_at !== "0001-01-01T00:00:00Z" ? (
+
+ ) : (
+ "N/A"
+ )}
+
+
+
+ Resolved At
+
+
+ {alert.resolved_at !== "0001-01-01T00:00:00Z" ? (
+
+ ) : (
+ "N/A"
+ )}
+
+
+ {alert.note && (
+ <>
+
+
Note
+
{alert.note}
+ >
+ )}
+
+
+ {showPayload && (
+
+ {JSON.stringify(alert.payload, null, 2)}
+
+ )}
+
+ {alert.sub_alerts.length > 0 && (
+ <>
+
+ Involved Alerts
+
+ {alert.sub_alerts
+ .sort(
+ (a: any, b: any) =>
+ new Date(b.created_at).getTime() -
+ new Date(a.created_at).getTime(),
+ )
+ .map((sa: any) => {
+ return (
+
+
+
+ }
+ textValue={sa.name}
+ >
+
+
{sa.name}
+
+
+ {sa.status || "N/A"}
+
+
+
+ Started:{" "}
+
+
+ {sa.resolved_at !==
+ "0001-01-01T00:00:00Z" && (
+
+ Resolved:{" "}
+
+
+ )}
+
+
+
+ {Object.entries(sa.labels).map(
+ ([key, value]: [string, any]) => {
+ return (
+
+ {key}: {value}
+
+ );
+ },
+ )}
+
+
+
+ );
+ })}
+
+ >
+ )}
+
+
+
+ {
+ router.push(`/flows/${alert.flow_id}`);
+ }}
+ >
+
+ View Flow
+
+ {alert.execution_id && (
+ {
+ router.push(
+ `/flows/${alert.flow_id}/execution/${alert.execution_id}`,
+ );
+ }}
+ >
+
+ View Execution
+
+ )}
+
+
+
+ {showDelete && (
+ handleDelete()}
+ >
+
+ Delete
+
+ )}
+
+ Close
+
+
+
+ >
+ )}
+
+
+
+ >
+ );
+}
diff --git a/services/frontend/components/modals/alerts/simulate.tsx b/services/frontend/components/modals/alerts/simulate.tsx
new file mode 100644
index 00000000..70dc10fc
--- /dev/null
+++ b/services/frontend/components/modals/alerts/simulate.tsx
@@ -0,0 +1,181 @@
+import type { UseDisclosureReturn } from "@heroui/use-disclosure";
+
+import { Icon } from "@iconify/react";
+import {
+ addToast,
+ Button,
+ Input,
+ Modal,
+ ModalBody,
+ ModalContent,
+ ModalFooter,
+ ModalHeader,
+ Textarea,
+} from "@heroui/react";
+import React from "react";
+
+import SimulateAlert from "@/lib/fetch/alert/POST/send";
+import ErrorCard from "@/components/error/ErrorCard";
+
+export default function SimulateAlertModal({
+ disclosure,
+ flow,
+}: {
+ disclosure: UseDisclosureReturn;
+ flow: any;
+}) {
+ const { isOpen, onOpenChange } = disclosure;
+
+ const [isLoading, setIsLoading] = React.useState(false);
+ const [error, setError] = React.useState(false);
+ const [errorText, setErrorText] = React.useState("");
+ const [errorMessage, setErrorMessage] = React.useState("");
+ const [target, setTarget] = React.useState(
+ // eslint-disable-next-line no-undef
+ `${window.location.origin}/alert/alertmanager`,
+ );
+ const [payload, setPayload] = React.useState(`{
+ "receiver": "${flow.id}",
+ "status": "firing",
+ "alerts": [
+ {
+ "status": "firing",
+ "labels": {
+ "alertname": "Test",
+ "dc": "eu-west-1",
+ "instance": "localhost:9090",
+ "job": "prometheus24"
+ },
+ "annotations": {
+ "description": "some description"
+ },
+ "startsAt": "2018-08-03T09:52:26.739266876+02:00",
+ "endsAt": "0001-01-01T00:00:00Z",
+ "generatorURL": "http://example.com:9090"
+ }
+ ],
+ "groupLabels": {
+ "alertname": "Test",
+ "job": "prometheus24"
+ },
+ "commonLabels": {
+ "alertname": "Test",
+ "dc": "eu-west-1",
+ "instance": "localhost:9090",
+ "job": "prometheus24"
+ },
+ "commonAnnotations": {
+ "description": "some description"
+ },
+ "externalURL": "http://example.com:9093",
+ "version": "4",
+ "groupKey": "test"
+}`);
+
+ async function sendPayload() {
+ setIsLoading(true);
+ const send = (await SimulateAlert(target, payload)) as any;
+
+ if (!send) {
+ setError(true);
+ setErrorText("Failed to send alert!");
+ setErrorMessage("Please try again later.");
+ setIsLoading(false);
+ addToast({
+ title: "Alert Simulation",
+ description: "Failed to send alert!",
+ color: "danger",
+ variant: "flat",
+ });
+
+ return;
+ }
+
+ if (!send.success) {
+ setError(true);
+ setErrorText(send.error);
+ setErrorMessage(send.message);
+ addToast({
+ title: "Alert Simulation",
+ description: "Failed to send alert!",
+ color: "danger",
+ variant: "flat",
+ });
+ } else {
+ onOpenChange();
+ setError(false);
+ setErrorText("");
+ setErrorMessage("");
+ addToast({
+ title: "Alert Simulation",
+ description: "Alert sent successfully!",
+ color: "success",
+ variant: "flat",
+ });
+ }
+
+ setIsLoading(false);
+ }
+
+ return (
+ <>
+
+
+ {(onClose) => (
+ <>
+
+
+
Simulate an Alert
+
+ With this Simulation you can test your Flow with a
+ predefined payload.
+
+
+
+
+ {error && (
+
+ )}
+
+
+
+
+
+ Close
+
+
+
+ Send
+
+
+ >
+ )}
+
+
+ >
+ );
+}
diff --git a/services/frontend/components/modals/executions/schedule.tsx b/services/frontend/components/modals/executions/schedule.tsx
index 54745699..df54984e 100644
--- a/services/frontend/components/modals/executions/schedule.tsx
+++ b/services/frontend/components/modals/executions/schedule.tsx
@@ -115,7 +115,6 @@ export default function ScheduleExecutionModal({
Select an date
{currentStep === 0 && (
+
+
setType("default")}
+ >
+
+
+ Default
+
+ Normal Flow with no specific triggers
+
+
+
+
setType("alert")}
+ >
+
+
+ Alert Based
+
+ Flow will be triggered by incoming alerts and will
+ show a dedicated alerting page
+
+
+
+
+ )}
+ {currentStep === 1 && (
)}
- {currentStep === 1 && (
+ {currentStep === 2 && (
<>
@@ -288,7 +339,6 @@ export default function CreateFlowModal({
variant="flat"
onPress={() => {
setCurrentStep(currentStep - 1);
- setDisableNext(false);
}}
>
Back
@@ -319,7 +369,7 @@ export default function CreateFlowModal({
) : (
diff --git a/services/frontend/components/modals/runner/changeStatus.tsx b/services/frontend/components/modals/runner/changeStatus.tsx
index 73498e0f..7ae65ff1 100644
--- a/services/frontend/components/modals/runner/changeStatus.tsx
+++ b/services/frontend/components/modals/runner/changeStatus.tsx
@@ -27,7 +27,7 @@ export default function ChangeRunnerStatusModal({
runner: any;
status: any;
}) {
- const { refreshRunners } = useRefreshCache();
+ const { refreshRunners, refreshProjectRunners } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
@@ -68,6 +68,9 @@ export default function ChangeRunnerStatusModal({
setErrorMessage("");
onOpenChange();
refreshRunners();
+ if (runner.project_id) {
+ refreshProjectRunners(runner.project_id);
+ }
addToast({
title: "Runner",
description: "Runner status updated successfully",
diff --git a/services/frontend/components/modals/runner/delete.tsx b/services/frontend/components/modals/runner/delete.tsx
index 8e85f44f..185be5bd 100644
--- a/services/frontend/components/modals/runner/delete.tsx
+++ b/services/frontend/components/modals/runner/delete.tsx
@@ -29,7 +29,7 @@ export default function DeleteRunnerModal({
disclosure: UseDisclosureReturn;
runner: any;
}) {
- const { refreshRunners } = useRefreshCache();
+ const { refreshRunners, refreshProjectRunners } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [flowLinks, setFlowLinks] = React.useState([]);
@@ -102,6 +102,9 @@ export default function DeleteRunnerModal({
variant: "flat",
});
refreshRunners();
+ if (runner.project_id) {
+ refreshProjectRunners(runner.project_id);
+ }
} else {
setError(true);
setErrorText(response.error);
diff --git a/services/frontend/components/modals/runner/edit.tsx b/services/frontend/components/modals/runner/edit.tsx
index 2bafd5bb..07cfb469 100644
--- a/services/frontend/components/modals/runner/edit.tsx
+++ b/services/frontend/components/modals/runner/edit.tsx
@@ -26,7 +26,7 @@ export default function EditRunnerModal({
disclosure: UseDisclosureReturn;
runner: any;
}) {
- const { refreshRunners } = useRefreshCache();
+ const { refreshRunners, refreshProjectRunners } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [isLoading, setIsLoading] = useState(false);
@@ -72,6 +72,9 @@ export default function EditRunnerModal({
variant: "flat",
});
refreshRunners();
+ if (runner.project_id) {
+ refreshProjectRunners(runner.project_id);
+ }
} else {
setApiError(true);
setApiErrorText(res.error);
diff --git a/services/frontend/components/navbar.tsx b/services/frontend/components/navbar.tsx
index a3f925a3..7190daf5 100644
--- a/services/frontend/components/navbar.tsx
+++ b/services/frontend/components/navbar.tsx
@@ -17,6 +17,7 @@ import {
Button,
Image,
Alert,
+ User,
} from "@heroui/react";
import { link as linkStyles } from "@heroui/theme";
import NextLink from "next/link";
@@ -250,14 +251,16 @@ export const Navbar = ({
-
diff --git a/services/frontend/components/ui/animatedcard.tsx b/services/frontend/components/ui/animatedcard.tsx
new file mode 100644
index 00000000..c6882f01
--- /dev/null
+++ b/services/frontend/components/ui/animatedcard.tsx
@@ -0,0 +1,75 @@
+"use client";
+import type { ReactNode } from "react";
+
+import { ArrowUpRightIcon } from "lucide-react";
+
+import { cn } from "@/lib/utils";
+
+import { useMouse } from "./usemouse";
+
+export const MainMenusGradientCard = ({
+ title,
+ description,
+ withArrow = false,
+ circleSize = 400,
+ className,
+ children,
+}: {
+ title: string;
+ description: string;
+ withArrow?: boolean;
+ circleSize?: number;
+ children?: ReactNode;
+ className?: string;
+}) => {
+ const [mouse, parentRef] = useMouse();
+
+ return (
+
+ {withArrow && (
+
+ )}
+
+
+ {children && (
+
+ {children}
+
+ )}
+
+
+ {title}
+
+
+ {description}
+
+
+
+ );
+};
diff --git a/services/frontend/components/ui/integrations.tsx b/services/frontend/components/ui/integrations.tsx
new file mode 100644
index 00000000..a60d26d8
--- /dev/null
+++ b/services/frontend/components/ui/integrations.tsx
@@ -0,0 +1,183 @@
+"use client";
+
+import { motion, useAnimation, useInView } from "framer-motion";
+import {
+ BarChart,
+ File,
+ Globe,
+ HeartHandshake,
+ Rss,
+ Shield,
+} from "lucide-react";
+import { JSX, useEffect, useId, useRef, useState } from "react";
+
+import { cn } from "@/lib/utils";
+
+import { Marquee } from "./marquee";
+
+const tiles = [
+ {
+ icon: ,
+ bg: (
+
+ ),
+ },
+ {
+ icon: ,
+ bg: (
+
+ ),
+ },
+ {
+ icon: ,
+ bg: (
+
+ ),
+ },
+ {
+ icon: ,
+ bg: (
+
+ ),
+ },
+ {
+ icon: ,
+ bg: (
+
+ ),
+ },
+ {
+ icon: ,
+ bg: (
+
+ ),
+ },
+];
+
+function shuffleArray(array: any[]) {
+ let currentIndex = array.length;
+ let randomIndex;
+
+ // While there remain elements to shuffle.
+ while (currentIndex !== 0) {
+ // Pick a remaining element.
+ randomIndex = Math.floor(Math.random() * currentIndex);
+ currentIndex--;
+ // And swap it with the current element.
+ [array[currentIndex], array[randomIndex]] = [
+ array[randomIndex],
+ array[currentIndex],
+ ];
+ }
+
+ return array;
+}
+
+function Card(card: { icon: JSX.Element; bg: JSX.Element }) {
+ const id = useId();
+ const controls = useAnimation();
+ const ref = useRef(null);
+ const inView = useInView(ref, { once: true });
+
+ useEffect(() => {
+ if (inView) {
+ controls.start({
+ opacity: 1,
+ transition: { delay: Math.random() * 2, ease: "easeOut", duration: 1 },
+ });
+ }
+ }, [controls, inView]);
+
+ return (
+
+ {card.icon}
+ {card.bg}
+
+ );
+}
+
+export function Integrations() {
+ const [randomTiles1, setRandomTiles1] = useState([]);
+ const [randomTiles2, setRandomTiles2] = useState([]);
+ const [randomTiles3, setRandomTiles3] = useState([]);
+ const [randomTiles4, setRandomTiles4] = useState([]);
+
+ useEffect(() => {
+ if (typeof window !== "undefined") {
+ // Ensures this runs client-side
+ setRandomTiles1(shuffleArray([...tiles]));
+ setRandomTiles2(shuffleArray([...tiles]));
+ setRandomTiles3(shuffleArray([...tiles]));
+ setRandomTiles4(shuffleArray([...tiles]));
+ }
+ }, []);
+
+ return (
+
+
+
+
+
+ {randomTiles1.map((review, idx) => (
+
+ ))}
+
+
+ {randomTiles2.map((review, idx) => (
+
+ ))}
+
+
+ {randomTiles1.map((review, idx) => (
+
+ ))}
+
+
+ {randomTiles2.map((review, idx) => (
+
+ ))}
+
+
+ {randomTiles3.map((review, idx) => (
+
+ ))}
+
+
+ {randomTiles4.map((review, idx) => (
+
+ ))}
+
+
+
+
+
+
+
+ );
+}
diff --git a/services/frontend/components/ui/marquee.tsx b/services/frontend/components/ui/marquee.tsx
new file mode 100644
index 00000000..6ac4948b
--- /dev/null
+++ b/services/frontend/components/ui/marquee.tsx
@@ -0,0 +1,52 @@
+import { cn } from "@/lib/utils";
+
+interface MarqueeProps {
+ className?: string;
+ reverse?: boolean;
+ pauseOnHover?: boolean;
+ // eslint-disable-next-line no-undef
+ children?: React.ReactNode;
+ vertical?: boolean;
+ repeat?: number;
+ [key: string]: any;
+}
+
+export function Marquee({
+ className,
+ reverse,
+ pauseOnHover = false,
+ children,
+ vertical = false,
+ repeat = 4,
+ ...props
+}: MarqueeProps) {
+ return (
+
+ {Array(repeat)
+ .fill(0)
+ .map((_, i) => (
+
+ {children}
+
+ ))}
+
+ );
+}
diff --git a/services/frontend/components/ui/usemouse.tsx b/services/frontend/components/ui/usemouse.tsx
new file mode 100644
index 00000000..3494e30d
--- /dev/null
+++ b/services/frontend/components/ui/usemouse.tsx
@@ -0,0 +1,67 @@
+"use client";
+import { type RefObject, useLayoutEffect, useRef, useState } from "react";
+
+interface MouseState {
+ x: number | null;
+ y: number | null;
+ elementX: number | null;
+ elementY: number | null;
+ elementPositionX: number | null;
+ elementPositionY: number | null;
+}
+
+// eslint-disable-next-line no-undef
+export function useMouse(): [MouseState, RefObject] {
+ const [state, setState] = useState({
+ x: null,
+ y: null,
+ elementX: null,
+ elementY: null,
+ elementPositionX: null,
+ elementPositionY: null,
+ });
+
+ // eslint-disable-next-line no-undef
+ const ref = useRef(null);
+
+ useLayoutEffect(() => {
+ // eslint-disable-next-line no-undef
+ const handleMouseMove = (event: MouseEvent) => {
+ const newState: Partial = {
+ x: event.pageX,
+ y: event.pageY,
+ };
+
+ // eslint-disable-next-line no-undef
+ if (ref.current instanceof Element) {
+ const { left, top } = ref.current.getBoundingClientRect();
+ // eslint-disable-next-line no-undef
+ const elementPositionX = left + window.scrollX;
+ // eslint-disable-next-line no-undef
+ const elementPositionY = top + window.scrollY;
+ const elementX = event.pageX - elementPositionX;
+ const elementY = event.pageY - elementPositionY;
+
+ newState.elementX = elementX;
+ newState.elementY = elementY;
+ newState.elementPositionX = elementPositionX;
+ newState.elementPositionY = elementPositionY;
+ }
+
+ setState((s) => ({
+ ...s,
+ ...newState,
+ }));
+ };
+
+ // eslint-disable-next-line no-undef
+ document.addEventListener("mousemove", handleMouseMove);
+
+ return () => {
+ // eslint-disable-next-line no-undef
+ document.removeEventListener("mousemove", handleMouseMove);
+ };
+ }, []);
+
+ return [state, ref];
+}
diff --git a/services/frontend/lib/fetch/alert/DELETE/alert.ts b/services/frontend/lib/fetch/alert/DELETE/alert.ts
new file mode 100644
index 00000000..cb90bb64
--- /dev/null
+++ b/services/frontend/lib/fetch/alert/DELETE/alert.ts
@@ -0,0 +1,69 @@
+"use server";
+
+import { cookies } from "next/headers";
+
+type Result = {
+ result: string;
+};
+
+type ErrorResponse = {
+ success: false;
+ error: string;
+ message: string;
+};
+
+type SuccessResponse = {
+ success: true;
+ data: Result;
+};
+
+export default async function DeleteAlert(
+ alertID: any,
+): Promise {
+ try {
+ const cookieStore = await cookies();
+ const token = cookieStore.get("session");
+
+ if (!token) {
+ return {
+ success: false,
+ error: "Authentication token not found",
+ message: "User is not authenticated",
+ };
+ }
+
+ const res = await fetch(
+ `${process.env.NEXT_PUBLIC_API_URL}/api/v1/alerts/${alertID}`,
+ {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: token.value,
+ },
+ },
+ );
+
+ if (!res.ok) {
+ const errorData = await res.json();
+
+ return {
+ success: false,
+ error: `API error: ${res.status} ${res.statusText}`,
+ message: errorData.message || "An error occurred",
+ };
+ }
+
+ const data = await res.json();
+
+ return {
+ success: true,
+ data,
+ };
+ } catch (error) {
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "Unknown error occurred",
+ message: "Failed to delete alert",
+ };
+ }
+}
diff --git a/services/frontend/lib/fetch/alert/POST/send.ts b/services/frontend/lib/fetch/alert/POST/send.ts
new file mode 100644
index 00000000..169e3d13
--- /dev/null
+++ b/services/frontend/lib/fetch/alert/POST/send.ts
@@ -0,0 +1,46 @@
+"use server";
+
+type ErrorResponse = {
+ success: false;
+ error: string;
+ message: string;
+};
+
+type SuccessResponse = {
+ success: true;
+};
+
+export default async function SimulateAlert(
+ target: any,
+ payload: any,
+): Promise {
+ try {
+ const res = await fetch(target, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: payload,
+ });
+
+ if (!res.ok) {
+ const errorData = await res.json();
+
+ return {
+ success: false,
+ error: `API error: ${res.status} ${res.statusText}`,
+ message: errorData.message || "An error occurred",
+ };
+ }
+
+ return {
+ success: true,
+ };
+ } catch (error) {
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "Unknown error occurred",
+ message: "Failed to send alert",
+ };
+ }
+}
diff --git a/services/frontend/lib/fetch/alert/alert.ts b/services/frontend/lib/fetch/alert/alert.ts
new file mode 100644
index 00000000..3853c11d
--- /dev/null
+++ b/services/frontend/lib/fetch/alert/alert.ts
@@ -0,0 +1,71 @@
+"use server";
+
+import { cookies } from "next/headers";
+
+type Alert = {
+ alert: object;
+};
+
+type ErrorResponse = {
+ success: false;
+ error: string;
+ message: string;
+};
+
+type SuccessResponse = {
+ success: true;
+ data: Alert;
+};
+
+export async function GetAlert(
+ alertID: any,
+): Promise {
+ try {
+ const cookieStore = await cookies();
+ const token = cookieStore.get("session");
+
+ if (!token) {
+ return {
+ success: false,
+ error: "Authentication token not found",
+ message: "User is not authenticated",
+ };
+ }
+
+ const res = await fetch(
+ `${process.env.NEXT_PUBLIC_API_URL}/api/v1/alerts/${alertID}`,
+ {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: token.value,
+ },
+ },
+ );
+
+ if (!res.ok) {
+ const errorData = await res.json();
+
+ return {
+ success: false,
+ error: `API error: ${res.status} ${res.statusText}`,
+ message: errorData.message || "An error occurred",
+ };
+ }
+
+ const data = await res.json();
+
+ return {
+ success: true,
+ data,
+ };
+ } catch (error) {
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "Unknown error occurred",
+ message: "Failed to fetch alert",
+ };
+ }
+}
+
+export default GetAlert;
diff --git a/services/frontend/lib/fetch/alert/alerts.ts b/services/frontend/lib/fetch/alert/alerts.ts
new file mode 100644
index 00000000..6e278e78
--- /dev/null
+++ b/services/frontend/lib/fetch/alert/alerts.ts
@@ -0,0 +1,69 @@
+"use server";
+
+import { cookies } from "next/headers";
+
+type Alerts = {
+ alerts: [];
+};
+
+type ErrorResponse = {
+ success: false;
+ error: string;
+ message: string;
+};
+
+type SuccessResponse = {
+ success: true;
+ data: Alerts;
+};
+
+export async function GetAlerts(): Promise {
+ try {
+ const cookieStore = await cookies();
+ const token = cookieStore.get("session");
+
+ if (!token) {
+ return {
+ success: false,
+ error: "Authentication token not found",
+ message: "User is not authenticated",
+ };
+ }
+
+ const res = await fetch(
+ `${process.env.NEXT_PUBLIC_API_URL}/api/v1/alerts/`,
+ {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: token.value,
+ },
+ },
+ );
+
+ if (!res.ok) {
+ const errorData = await res.json();
+
+ return {
+ success: false,
+ error: `API error: ${res.status} ${res.statusText}`,
+ message: errorData.message || "An error occurred",
+ };
+ }
+
+ const data = await res.json();
+
+ return {
+ success: true,
+ data,
+ };
+ } catch (error) {
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "Unknown error occurred",
+ message: "Failed to fetch alerts",
+ };
+ }
+}
+
+export default GetAlerts;
diff --git a/services/frontend/lib/fetch/flow/POST/CreateFlow.ts b/services/frontend/lib/fetch/flow/POST/CreateFlow.ts
index d349c5a1..96dfe1dc 100644
--- a/services/frontend/lib/fetch/flow/POST/CreateFlow.ts
+++ b/services/frontend/lib/fetch/flow/POST/CreateFlow.ts
@@ -18,6 +18,7 @@ type SuccessResponse = {
};
export default async function CreateFlow(
+ type: string,
name: string,
description: string,
folderId: string,
@@ -45,6 +46,7 @@ export default async function CreateFlow(
Authorization: token.value,
},
body: JSON.stringify({
+ type,
name,
description,
folder_id: folderId,
diff --git a/services/frontend/lib/fetch/flow/PUT/UpdateFlow.ts b/services/frontend/lib/fetch/flow/PUT/UpdateFlow.ts
index 4147d5b8..3c6bc64e 100644
--- a/services/frontend/lib/fetch/flow/PUT/UpdateFlow.ts
+++ b/services/frontend/lib/fetch/flow/PUT/UpdateFlow.ts
@@ -28,6 +28,9 @@ export default async function UpdateFlow(
failurePipelineID: string,
scheduleEveryValue: number,
scheduleEveryUnit: string,
+ groupAlerts: boolean,
+ groupAlertsIdentifier: string,
+ alertThreshold: number,
): Promise {
try {
const cookieStore = await cookies();
@@ -51,6 +54,9 @@ export default async function UpdateFlow(
failure_pipeline_id: failurePipelineID,
schedule_every_value: scheduleEveryValue,
schedule_every_unit: scheduleEveryUnit,
+ group_alerts: groupAlerts,
+ group_alerts_identifier: groupAlertsIdentifier,
+ alert_threshold: alertThreshold,
}),
},
);
diff --git a/services/frontend/lib/swr/hooks/flows.ts b/services/frontend/lib/swr/hooks/flows.ts
index 45bc11a0..1ccf1d1f 100644
--- a/services/frontend/lib/swr/hooks/flows.ts
+++ b/services/frontend/lib/swr/hooks/flows.ts
@@ -18,6 +18,7 @@ import GetProjectApiKeys from "@/lib/fetch/project/tokens";
import GetExecution from "@/lib/fetch/executions/execution";
import GetExecutions from "@/lib/fetch/executions/all";
import GetExecutionSteps from "@/lib/fetch/executions/steps";
+import GetFlowAlerts from "@/lib/fetch/flow/alerts";
// Hook for fetching a single flow
export function useFlow(flowId: string) {
@@ -34,6 +35,21 @@ export function useFlow(flowId: string) {
};
}
+// Hook for fetching flow alert
+export function useFlowAlerts(flowId: string) {
+ const { data, error, mutate, isLoading } = useSWR(
+ flowId ? `flow-alerts-${flowId}` : null,
+ () => GetFlowAlerts(flowId),
+ );
+
+ return {
+ alerts: data?.success ? data.data.alerts : [],
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
// Hook for fetching flow executions
export function useFlowExecutions(flowId: string) {
const { data, error, mutate, isLoading } = useSWR(
diff --git a/services/frontend/tailwind.config.ts b/services/frontend/tailwind.config.ts
index 8b919552..d768a9fd 100644
--- a/services/frontend/tailwind.config.ts
+++ b/services/frontend/tailwind.config.ts
@@ -15,8 +15,18 @@ module.exports = {
},
animation: {
gradient: "gradient 8s linear infinite",
+ marquee: "marquee var(--duration) linear infinite",
+ "marquee-vertical": "marquee-vertical var(--duration) linear infinite",
},
keyframes: {
+ marquee: {
+ from: { transform: "translateX(0)" },
+ to: { transform: "translateX(calc(-100% - var(--gap)))" },
+ },
+ "marquee-vertical": {
+ from: { transform: "translateY(0)" },
+ to: { transform: "translateY(calc(-100% - var(--gap)))" },
+ },
gradient: {
to: {
backgroundPosition: "var(--bg-size) 0",
From 032e3ff266227be147f45d07e9996c2b174da230 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Mon, 8 Sep 2025 09:30:48 +0200
Subject: [PATCH 22/45] feat: implement alerts management with pagination,
filtering, and cache refresh functionality
---
.../httperror/internalServerError.go | 7 +-
.../backend/handlers/alerts/get_alerts.go | 76 ++++++-
services/backend/handlers/flows/get_alerts.go | 53 ++++-
.../frontend/components/alerts/alerts.tsx | 203 ++++++++++++++++++
services/frontend/components/alerts/list.tsx | 41 +---
.../components/flows/flow/page-client.tsx | 4 -
.../frontend/components/flows/flow/tabs.tsx | 11 +-
.../components/modals/alerts/delete.tsx | 7 +-
.../components/modals/alerts/simulate.tsx | 3 +
services/frontend/config/site.ts | 8 +
services/frontend/lib/fetch/alert/alerts.ts | 11 +-
services/frontend/lib/fetch/flow/alerts.ts | 8 +-
.../lib/functions/userAlertsStyle.tsx | 24 +++
.../lib/functions/userExecutionsStyle.tsx | 17 ++
services/frontend/lib/swr/hooks/flows.ts | 44 ++++
.../frontend/lib/swr/hooks/useRefreshCache.ts | 26 +++
16 files changed, 474 insertions(+), 69 deletions(-)
create mode 100644 services/frontend/components/alerts/alerts.tsx
create mode 100644 services/frontend/lib/functions/userAlertsStyle.tsx
diff --git a/services/backend/functions/httperror/internalServerError.go b/services/backend/functions/httperror/internalServerError.go
index 4b59fff7..db259e01 100644
--- a/services/backend/functions/httperror/internalServerError.go
+++ b/services/backend/functions/httperror/internalServerError.go
@@ -7,6 +7,9 @@ import (
)
func InternalServerError(context *gin.Context, message string, err error) {
- context.JSON(http.StatusInternalServerError, gin.H{"message": message, "error": err.Error()})
- context.Abort()
+ errorMessage := "Unknown error"
+ if err != nil {
+ errorMessage = err.Error()
+ }
+ context.JSON(http.StatusInternalServerError, gin.H{"message": message, "error": errorMessage})
}
diff --git a/services/backend/handlers/alerts/get_alerts.go b/services/backend/handlers/alerts/get_alerts.go
index 892c7356..9a08e697 100644
--- a/services/backend/handlers/alerts/get_alerts.go
+++ b/services/backend/handlers/alerts/get_alerts.go
@@ -1,9 +1,10 @@
package alerts
import (
+ "fmt"
"net/http"
+ "strings"
- "github.com/google/uuid"
"github.com/v1Flows/exFlow/services/backend/functions/auth"
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/httperror"
@@ -21,23 +22,49 @@ func GetMultiple(context *gin.Context, db *bun.DB) {
return
}
+ // Parse pagination params
+ limit := 20
+ offset := 0
+ if l := context.Query("limit"); l != "" {
+ fmt.Sscanf(l, "%d", &limit)
+ }
+ if o := context.Query("offset"); o != "" {
+ fmt.Sscanf(o, "%d", &offset)
+ }
+
+ // Parse status filter (comma-separated)
+ statusParam := context.Query("status")
+ var statusList []string
+ if statusParam != "" {
+ statusList = strings.Split(statusParam, ",")
+ }
+
// get all flows where the user is a member
flows := make([]models.Flows, 0)
- err = db.NewSelect().Model(&flows).Column("id").Where("project_id::uuid IN (SELECT project_id::uuid FROM project_members WHERE user_id = ? AND invite_pending = false)", userID).Scan(context)
+ err = db.NewSelect().Model(&flows).Column("id", "project_id").Where("project_id::uuid IN (SELECT project_id::uuid FROM project_members WHERE user_id = ? AND invite_pending = false)", userID).Scan(context)
if err != nil {
httperror.InternalServerError(context, "Error collecting flows from db", err)
return
}
+ // put flow ids in an array
+ flowsArray := make([]string, 0)
+ for _, flow := range flows {
+ flowsArray = append(flowsArray, flow.ID.String())
+ }
+
alerts := make([]models.Alerts, 0)
+ query := db.NewSelect().Model(&alerts).
+ Where("flow_id IN (?)", bun.In(flowsArray))
- // get all alerts for each flow
- flowIDs := make([]uuid.UUID, len(flows))
- for i, flow := range flows {
- flowIDs[i] = flow.ID
+ if len(statusList) > 0 {
+ query = query.Where("status IN (?)", bun.In(statusList))
}
- err = db.NewSelect().Model(&alerts).Where("flow_id IN (?)", bun.In(flowIDs)).Order("created_at DESC").Scan(context)
+ err = query.Order("created_at DESC").
+ Limit(limit).
+ Offset(offset).
+ Scan(context)
if err != nil {
httperror.InternalServerError(context, "Error collecting alerts from db", err)
return
@@ -45,7 +72,20 @@ func GetMultiple(context *gin.Context, db *bun.DB) {
for i := range alerts {
if alerts[i].Encrypted {
- alerts[i].Payload, err = encryption.DecryptPayload(alerts[i].Payload, alerts[i].FlowID, db)
+ // get flow to find project_id and use the already fetched flows to avoid another db call
+ var flowProjectID string
+ for _, flow := range flows {
+ if flow.ID.String() == alerts[i].FlowID {
+ flowProjectID = flow.ProjectID
+ break
+ }
+ }
+ if flowProjectID == "" {
+ continue
+ }
+
+ // Decrypt using the project ID found
+ alerts[i].Payload, err = encryption.DecryptPayload(alerts[i].Payload, flowProjectID, db)
if err != nil {
httperror.InternalServerError(context, "Error decrypting alert", err)
return
@@ -53,5 +93,23 @@ func GetMultiple(context *gin.Context, db *bun.DB) {
}
}
- context.JSON(http.StatusOK, gin.H{"alerts": alerts})
+ // Count total alerts for pagination (with status filter)
+ countQuery := db.NewSelect().
+ Model((*models.Alerts)(nil)).
+ Where("flow_id IN (?)", bun.In(flowsArray))
+ if len(statusList) > 0 {
+ countQuery = countQuery.Where("status IN (?)", bun.In(statusList))
+ }
+ totalAlerts, err := countQuery.Count(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error counting alerts", err)
+ return
+ }
+
+ context.JSON(http.StatusOK, gin.H{
+ "alerts": alerts,
+ "limit": limit,
+ "offset": offset,
+ "total": totalAlerts,
+ })
}
diff --git a/services/backend/handlers/flows/get_alerts.go b/services/backend/handlers/flows/get_alerts.go
index 017c2126..2093cbc2 100644
--- a/services/backend/handlers/flows/get_alerts.go
+++ b/services/backend/handlers/flows/get_alerts.go
@@ -2,7 +2,9 @@ package flows
import (
"errors"
+ "fmt"
"net/http"
+ "strings"
"github.com/v1Flows/exFlow/services/backend/functions/encryption"
"github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
@@ -17,6 +19,23 @@ import (
func GetFlowAlerts(context *gin.Context, db *bun.DB) {
flowID := context.Param("flowID")
+ // Parse pagination params
+ limit := 20
+ offset := 0
+ if l := context.Query("limit"); l != "" {
+ fmt.Sscanf(l, "%d", &limit)
+ }
+ if o := context.Query("offset"); o != "" {
+ fmt.Sscanf(o, "%d", &offset)
+ }
+
+ // Parse status filter (comma-separated)
+ statusParam := context.Query("status")
+ var statusList []string
+ if statusParam != "" {
+ statusList = strings.Split(statusParam, ",")
+ }
+
// get flow
var flow models.Flows
err := db.NewSelect().Model(&flow).Where("id = ?", flowID).Scan(context)
@@ -37,9 +56,32 @@ func GetFlowAlerts(context *gin.Context, db *bun.DB) {
}
alerts := make([]models.Alerts, 0)
- err = db.NewSelect().Model(&alerts).Where("flow_id = ?", flowID).Order("created_at DESC").Scan(context)
+ query := db.NewSelect().Model(&alerts).
+ Where("flow_id = ?", flowID)
+
+ if len(statusList) > 0 {
+ query = query.Where("status IN (?)", bun.In(statusList))
+ }
+
+ err = query.Order("created_at DESC").
+ Limit(limit).
+ Offset(offset).
+ Scan(context)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting alerts from db", err)
+ return
+ }
+
+ // Count total alerts for pagination (with status filter)
+ countQuery := db.NewSelect().
+ Model((*models.Alerts)(nil)).
+ Where("flow_id = ?", flowID)
+ if len(statusList) > 0 {
+ countQuery = countQuery.Where("status IN (?)", bun.In(statusList))
+ }
+ totalAlerts, err := countQuery.Count(context)
if err != nil {
- httperror.InternalServerError(context, "Error collecting flow alerts from db", err)
+ httperror.InternalServerError(context, "Error counting alerts", err)
return
}
@@ -53,5 +95,10 @@ func GetFlowAlerts(context *gin.Context, db *bun.DB) {
}
}
- context.JSON(http.StatusOK, gin.H{"alerts": alerts})
+ context.JSON(http.StatusOK, gin.H{
+ "alerts": alerts,
+ "limit": limit,
+ "offset": offset,
+ "total": totalAlerts,
+ })
}
diff --git a/services/frontend/components/alerts/alerts.tsx b/services/frontend/components/alerts/alerts.tsx
new file mode 100644
index 00000000..396a35ef
--- /dev/null
+++ b/services/frontend/components/alerts/alerts.tsx
@@ -0,0 +1,203 @@
+import {
+ Button,
+ ButtonGroup,
+ Card,
+ CardBody,
+ Dropdown,
+ DropdownItem,
+ DropdownMenu,
+ DropdownTrigger,
+ Pagination,
+ Spacer,
+ Spinner,
+ Tooltip,
+} from "@heroui/react";
+import { Icon } from "@iconify/react";
+import { useMemo, useState } from "react";
+import NumberFlow from "@number-flow/react";
+
+import { useAlerts, useFlowAlertsPaginated } from "@/lib/swr/hooks/flows";
+import { useAlertsStyleStore } from "@/lib/functions/userAlertsStyle";
+
+import AlertsList from "./list";
+
+export default function Alerts({
+ runners,
+ flow,
+ canEdit,
+}: {
+ runners: any;
+ flow?: any;
+ canEdit?: boolean;
+}) {
+ const { displayStyle, setDisplayStyle } = useAlertsStyleStore();
+ const [statusFilter, setStatusFilter] = useState(new Set([]) as any);
+
+ // pagination
+ const [page, setPage] = useState(1);
+ const limit = 6;
+
+ // Calculate offset using page directly for now (will be validated later)
+ const offset = (page - 1) * limit;
+
+ // Convert statusFilter to string for API
+ const statusFilterString =
+ statusFilter.size > 0 ? Array.from(statusFilter).join(",") : null;
+
+ // Always call both hooks but only use the relevant one
+ const flowAlertsResult = useFlowAlertsPaginated(
+ flow.id || null,
+ limit,
+ offset,
+ statusFilterString,
+ );
+ const allAlertsResult = useAlerts(
+ flow.id ? 0 : limit,
+ flow.id ? 0 : offset,
+ flow.id ? null : statusFilterString,
+ );
+
+ // Choose the right result based on whether we have a flowID
+ const {
+ alerts,
+ total: totalAlerts,
+ isLoading: loading,
+ refresh,
+ } = flow.id ? flowAlertsResult : allAlertsResult;
+
+ const items = useMemo(() => {
+ return alerts || [];
+ }, [alerts]);
+
+ // Calculate total pages
+ const totalPages = Math.max(1, Math.ceil(totalAlerts / limit));
+
+ // Ensure page is never higher than total pages
+ const safePage = Math.min(page, totalPages);
+
+ // If safe page is different from current page, update it
+ if (safePage !== page && totalPages > 0 && !loading) {
+ setPage(safePage);
+ }
+
+ return (
+
+
+
+
+ Total Alerts:
+
+
+
+
+
+ }
+ variant={statusFilter.size > 0 ? "solid" : "flat"}
+ >
+ Filter
+
+
+ {
+ setStatusFilter(e);
+ setPage(1); // Reset to first page when filter changes
+ }}
+ >
+
+ }
+ >
+ Firing
+
+
+ }
+ >
+ Resolved
+
+
+
+
+
+ }
+ variant="flat"
+ onPress={() => {
+ refresh();
+ }}
+ >
+ Refresh
+
+
+
+
+ }
+ variant={displayStyle === "list" ? "solid" : "flat"}
+ onPress={() => {
+ setDisplayStyle("list");
+ setPage(1);
+ }}
+ />
+
+
+
+
+
+
+
+ {loading ? (
+
+
+
+ ) : (
+ <>
+ {displayStyle === "list" && (
+
+ )}
+ >
+ )}
+
+
+
setPage(newPage)}
+ />
+
+
+
+ );
+}
diff --git a/services/frontend/components/alerts/list.tsx b/services/frontend/components/alerts/list.tsx
index 64e100d3..a71d2bd2 100644
--- a/services/frontend/components/alerts/list.tsx
+++ b/services/frontend/components/alerts/list.tsx
@@ -8,30 +8,25 @@ import {
Chip,
Listbox,
ListboxItem,
- Pagination,
ScrollShadow,
Spacer,
useDisclosure,
} from "@heroui/react";
import { Icon } from "@iconify/react";
-import { useMemo, useState } from "react";
+import { useState } from "react";
import ReactTimeago from "react-timeago";
import { IconWrapper } from "@/lib/IconWrapper";
import AlertDrawer from "@/components/modals/alerts/details";
export default function AlertsList({
- compactMode,
alerts,
runners,
flows,
- maxAlerts,
canEdit,
showDelete,
showFlowChip,
}: {
- compactMode: boolean;
- maxAlerts: number;
alerts: any;
runners: any;
flows?: any;
@@ -43,28 +38,15 @@ export default function AlertsList({
const [targetAlert, setTargetAlert] = useState(null);
- // pagination
- const [page, setPage] = useState(1);
- const pages = Math.ceil(
- alerts.filter((alert: any) => !alert.parent_id).length / maxAlerts,
- );
- const items = useMemo(() => {
- const filteredAlerts = alerts.filter((alert: any) => !alert.parent_id);
- const start = (page - 1) * maxAlerts;
- const end = start + maxAlerts;
-
- return filteredAlerts.slice(start, end);
- }, [page, alerts]);
-
return (
-
- {items.map((alert: any) => (
+
+ {alerts.map((alert: any) => (
{
setTargetAlert(alert);
alertDrawer.onOpenChange();
@@ -74,7 +56,7 @@ export default function AlertsList({
))}
- {!compactMode && (
-
- )}
}
>
-
)}
diff --git a/services/frontend/components/modals/alerts/delete.tsx b/services/frontend/components/modals/alerts/delete.tsx
index 9bcf1fbd..400f07e9 100644
--- a/services/frontend/components/modals/alerts/delete.tsx
+++ b/services/frontend/components/modals/alerts/delete.tsx
@@ -10,11 +10,11 @@ import {
ModalHeader,
Snippet,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import React from "react";
import DeleteAlert from "@/lib/fetch/alert/DELETE/alert";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function DeleteAlertModal({
disclosure,
@@ -23,8 +23,7 @@ export default function DeleteAlertModal({
disclosure: UseDisclosureReturn;
alert: any;
}) {
- const router = useRouter();
-
+ const { refreshAllAlertCaches } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [isDeleteLoading, setIsDeleteLoading] = React.useState(false);
@@ -55,7 +54,7 @@ export default function DeleteAlertModal({
color: "success",
variant: "flat",
});
- router.refresh();
+ refreshAllAlertCaches(alert.flow_id);
onOpenChange();
} else {
setError(true);
diff --git a/services/frontend/components/modals/alerts/simulate.tsx b/services/frontend/components/modals/alerts/simulate.tsx
index 70dc10fc..4901069b 100644
--- a/services/frontend/components/modals/alerts/simulate.tsx
+++ b/services/frontend/components/modals/alerts/simulate.tsx
@@ -16,6 +16,7 @@ import React from "react";
import SimulateAlert from "@/lib/fetch/alert/POST/send";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function SimulateAlertModal({
disclosure,
@@ -24,6 +25,7 @@ export default function SimulateAlertModal({
disclosure: UseDisclosureReturn;
flow: any;
}) {
+ const { refreshAllAlertCaches } = useRefreshCache();
const { isOpen, onOpenChange } = disclosure;
const [isLoading, setIsLoading] = React.useState(false);
@@ -102,6 +104,7 @@ export default function SimulateAlertModal({
variant: "flat",
});
} else {
+ refreshAllAlertCaches(flow.id);
onOpenChange();
setError(false);
setErrorText("");
diff --git a/services/frontend/config/site.ts b/services/frontend/config/site.ts
index a2bda5b5..4c043585 100644
--- a/services/frontend/config/site.ts
+++ b/services/frontend/config/site.ts
@@ -17,6 +17,10 @@ export const siteConfig = {
label: "Flows",
href: "/flows",
},
+ {
+ label: "Alerts",
+ href: "/alerts",
+ },
{
label: "Runners",
href: "/runners",
@@ -35,6 +39,10 @@ export const siteConfig = {
label: "Flows",
href: "/flows",
},
+ {
+ label: "Alerts",
+ href: "/alerts",
+ },
{
label: "Runners",
href: "/runners",
diff --git a/services/frontend/lib/fetch/alert/alerts.ts b/services/frontend/lib/fetch/alert/alerts.ts
index 6e278e78..603830c3 100644
--- a/services/frontend/lib/fetch/alert/alerts.ts
+++ b/services/frontend/lib/fetch/alert/alerts.ts
@@ -4,6 +4,9 @@ import { cookies } from "next/headers";
type Alerts = {
alerts: [];
+ limit: number;
+ offset: number;
+ total: number;
};
type ErrorResponse = {
@@ -17,7 +20,11 @@ type SuccessResponse = {
data: Alerts;
};
-export async function GetAlerts(): Promise {
+export async function GetAlerts(
+ limit: number = 10,
+ offset: number = 0,
+ status: string | null = null,
+): Promise {
try {
const cookieStore = await cookies();
const token = cookieStore.get("session");
@@ -31,7 +38,7 @@ export async function GetAlerts(): Promise {
}
const res = await fetch(
- `${process.env.NEXT_PUBLIC_API_URL}/api/v1/alerts/`,
+ `${process.env.NEXT_PUBLIC_API_URL}/api/v1/alerts?limit=${limit}&offset=${offset}&status=${status || ""}`,
{
method: "GET",
headers: {
diff --git a/services/frontend/lib/fetch/flow/alerts.ts b/services/frontend/lib/fetch/flow/alerts.ts
index 5e88d17a..0d6845a9 100644
--- a/services/frontend/lib/fetch/flow/alerts.ts
+++ b/services/frontend/lib/fetch/flow/alerts.ts
@@ -4,6 +4,9 @@ import { cookies } from "next/headers";
type Alerts = {
alerts: [];
+ limit: number;
+ offset: number;
+ total: number;
};
type ErrorResponse = {
@@ -19,6 +22,9 @@ type SuccessResponse = {
export async function GetFlowAlerts(
flowID: any,
+ limit: number = 10,
+ offset: number = 0,
+ status: string | null = null,
): Promise {
try {
const cookieStore = await cookies();
@@ -33,7 +39,7 @@ export async function GetFlowAlerts(
}
const res = await fetch(
- `${process.env.NEXT_PUBLIC_API_URL}/api/v1/flows/${flowID}/alerts`,
+ `${process.env.NEXT_PUBLIC_API_URL}/api/v1/flows/${flowID}/alerts?limit=${limit}&offset=${offset}&status=${status || ""}`,
{
method: "GET",
headers: {
diff --git a/services/frontend/lib/functions/userAlertsStyle.tsx b/services/frontend/lib/functions/userAlertsStyle.tsx
new file mode 100644
index 00000000..1c7ee8d3
--- /dev/null
+++ b/services/frontend/lib/functions/userAlertsStyle.tsx
@@ -0,0 +1,24 @@
+import { create } from "zustand";
+import { persist } from "zustand/middleware";
+
+type DisplayStyle = "list";
+
+interface AlertsStyleStore {
+ displayStyle: DisplayStyle;
+ setDisplayStyle: (style: DisplayStyle) => void;
+}
+
+export const useAlertsStyleStore = create()(
+ persist(
+ (set) => ({
+ displayStyle: "list",
+ setDisplayStyle: (style) => set({ displayStyle: style }),
+ }),
+ {
+ name: "alertsDisplayStyle", // key in localStorage
+ },
+ ),
+);
+
+// Usage example in a component:
+// const { displayStyle, setDisplayStyle } = useAlertsStyleStore();
diff --git a/services/frontend/lib/functions/userExecutionsStyle.tsx b/services/frontend/lib/functions/userExecutionsStyle.tsx
index 1aff4a91..8ef13ee5 100644
--- a/services/frontend/lib/functions/userExecutionsStyle.tsx
+++ b/services/frontend/lib/functions/userExecutionsStyle.tsx
@@ -8,6 +8,11 @@ interface ExecutionsStyleStore {
setDisplayStyle: (style: DisplayStyle) => void;
}
+interface AlertsStyleStore {
+ displayStyle: DisplayStyle;
+ setDisplayStyle: (style: DisplayStyle) => void;
+}
+
export const useExecutionsStyleStore = create()(
persist(
(set) => ({
@@ -20,5 +25,17 @@ export const useExecutionsStyleStore = create()(
),
);
+export const useAlertsStyleStore = create()(
+ persist(
+ (set) => ({
+ displayStyle: "list",
+ setDisplayStyle: (style) => set({ displayStyle: style }),
+ }),
+ {
+ name: "alertsDisplayStyle", // key in localStorage
+ },
+ ),
+);
+
// Usage example in a component:
// const { displayStyle, setDisplayStyle } = useExecutionsStyleStore();
diff --git a/services/frontend/lib/swr/hooks/flows.ts b/services/frontend/lib/swr/hooks/flows.ts
index 1ccf1d1f..beac3178 100644
--- a/services/frontend/lib/swr/hooks/flows.ts
+++ b/services/frontend/lib/swr/hooks/flows.ts
@@ -19,6 +19,7 @@ import GetExecution from "@/lib/fetch/executions/execution";
import GetExecutions from "@/lib/fetch/executions/all";
import GetExecutionSteps from "@/lib/fetch/executions/steps";
import GetFlowAlerts from "@/lib/fetch/flow/alerts";
+import GetAlerts from "@/lib/fetch/alert/alerts";
// Hook for fetching a single flow
export function useFlow(flowId: string) {
@@ -50,6 +51,49 @@ export function useFlowAlerts(flowId: string) {
};
}
+// Hook for fetching paginated flow alerts with filters
+export function useFlowAlertsPaginated(
+ flowId: string,
+ limit: number = 10,
+ offset: number = 0,
+ status: string | null = null,
+) {
+ const { data, error, mutate, isLoading } = useSWR(
+ flowId
+ ? `flow-alerts-paginated-${flowId}-${limit}-${offset}-${status || "all"}`
+ : null,
+ () => GetFlowAlerts(flowId, limit, offset, status),
+ );
+
+ return {
+ alerts: data?.success ? data.data.alerts : [],
+ total: data?.success ? data.data.total : 0,
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
+// Hook for fetching all alerts with pagination and filters
+export function useAlerts(
+ limit: number = 10,
+ offset: number = 0,
+ status: string | null = null,
+) {
+ const { data, error, mutate, isLoading } = useSWR(
+ limit > 0 ? `alerts-${limit}-${offset}-${status || "all"}` : null,
+ () => GetAlerts(limit, offset, status),
+ );
+
+ return {
+ alerts: data?.success ? data.data.alerts : [],
+ total: data?.success ? data.data.total : 0,
+ isLoading,
+ isError: error || (data && !data.success),
+ refresh: mutate,
+ };
+}
+
// Hook for fetching flow executions
export function useFlowExecutions(flowId: string) {
const { data, error, mutate, isLoading } = useSWR(
diff --git a/services/frontend/lib/swr/hooks/useRefreshCache.ts b/services/frontend/lib/swr/hooks/useRefreshCache.ts
index 0bb1238f..611d49ad 100644
--- a/services/frontend/lib/swr/hooks/useRefreshCache.ts
+++ b/services/frontend/lib/swr/hooks/useRefreshCache.ts
@@ -53,6 +53,32 @@ export function useRefreshCache() {
refreshFolderExecutions: (folderId: string) =>
mutate(`folder-executions-${folderId}`),
+ // Helper to refresh all alert-related caches (useful after deletion)
+ refreshAllAlertCaches: (flowId?: string) => {
+ // Refresh all paginated alert caches with common pagination values
+ const limits = [4, 6, 10]; // Common limits used in the app
+ const offsets = [0, 10, 20, 30]; // Common offset values
+ const statuses = [null, "all"]; // Common status filters
+
+ limits.forEach((limit) => {
+ offsets.forEach((offset) => {
+ statuses.forEach((status) => {
+ mutate(`alerts-${limit}-${offset}-${status || "all"}`);
+ if (flowId) {
+ mutate(
+ `flow-alerts-paginated-${flowId}-${limit}-${offset}-${status || "all"}`,
+ );
+ }
+ });
+ });
+ });
+
+ // Refresh specific flow alerts if flowId provided
+ if (flowId) {
+ mutate(`flow-alerts-${flowId}`);
+ }
+ },
+
// Helper to refresh all execution-related caches (useful after deletion)
refreshAllExecutionCaches: (flowId?: string) => {
// Refresh general execution caches
From ebf41043bf7e25a411f852aca939c66ba4109c8c Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Mon, 8 Sep 2025 10:35:41 +0200
Subject: [PATCH 23/45] feat: enhance user stats endpoint to include detailed
execution and alert statistics
---
services/backend/handlers/users/get_stats.go | 155 +++++++----
.../frontend/components/dashboard/home.tsx | 6 +-
.../components/dashboard/stats-charts.tsx | 260 ++++++++++++++++++
.../frontend/components/dashboard/stats.tsx | 232 ----------------
4 files changed, 372 insertions(+), 281 deletions(-)
create mode 100644 services/frontend/components/dashboard/stats-charts.tsx
delete mode 100644 services/frontend/components/dashboard/stats.tsx
diff --git a/services/backend/handlers/users/get_stats.go b/services/backend/handlers/users/get_stats.go
index dca410c9..18c0522c 100644
--- a/services/backend/handlers/users/get_stats.go
+++ b/services/backend/handlers/users/get_stats.go
@@ -1,9 +1,7 @@
package users
import (
- "fmt"
"net/http"
- "strconv"
"time"
"github.com/v1Flows/exFlow/services/backend/functions/auth"
@@ -50,70 +48,135 @@ func GetUserStats(context *gin.Context, db *bun.DB) {
}
type Stats struct {
- Date string `json:"date"`
- Weekday string `json:"weekday"`
- Value int `json:"value"`
- IsCurrent bool `json:"is_current"`
+ Weekday string `json:"weekday"`
+ TotalExecutions int `json:"total_executions"`
+ Success int `json:"success"`
+ Error int `json:"error"`
+ Pending int `json:"pending"`
+ Running int `json:"running"`
+ Canceled int `json:"canceled"`
+ Scheduled int `json:"scheduled"`
+ NoPatternMatch int `json:"noPatternMatch"`
+ Recovered int `json:"recovered"`
}
- var executionStats []Stats
+ type AlertStats struct {
+ Weekday string `json:"weekday"`
+ TotalAlerts int `json:"total_alerts"`
+ Firing int `json:"firing"`
+ Resolved int `json:"resolved"`
+ }
+
+ type RawExecutionStats struct {
+ Date string `json:"date"`
+ Status string `json:"status"`
+ Value int `json:"value"`
+ }
+
+ var rawExecutionStats []RawExecutionStats
err = db.NewSelect().
- TableExpr("(SELECT DATE(created_at) as date, COUNT(*) as value FROM executions WHERE flow_id IN (?) AND created_at >= NOW() - INTERVAL '7 days' GROUP BY DATE(created_at)) AS subquery", bun.In(flowsArray)).
- Scan(context, &executionStats)
+ TableExpr("(SELECT DATE(created_at) as date, status, COUNT(*) as value FROM executions WHERE flow_id IN (?) AND created_at >= NOW() - INTERVAL '7 days' GROUP BY DATE(created_at), status) AS subquery", bun.In(flowsArray)).
+ Scan(context, &rawExecutionStats)
if err != nil {
httperror.InternalServerError(context, "Error collecting execution stats from db", err)
return
}
- // Create a map to store the execution stats by weekday of the week
- statsMap := make(map[string]int)
- for _, stat := range executionStats {
+ // Create a map to store the execution stats by weekday and status
+ statsMap := make(map[string]map[string]int)
+ totalStatsMap := make(map[string]int)
+ for _, stat := range rawExecutionStats {
date, _ := time.Parse("2006-01-02", stat.Date)
- weekday := date.Weekday().String()[:2]
- statsMap[weekday] += stat.Value
+ weekday := date.Weekday().String()[:3]
+
+ if statsMap[weekday] == nil {
+ statsMap[weekday] = make(map[string]int)
+ }
+
+ statsMap[weekday][stat.Status] += stat.Value
+ totalStatsMap[weekday] += stat.Value
}
// Generate the execution stats for each weekday of the week
- executionStats = make([]Stats, 0)
+ var executionStats []Stats
for i := 6; i >= 0; i-- { // Look from the current weekday in the past
- weekday := time.Now().AddDate(0, 0, -i).Weekday().String()[:2]
- isCurrent := i == 0
- executionStats = append(executionStats, Stats{Weekday: weekday, Value: statsMap[weekday], IsCurrent: isCurrent})
- }
-
- // Determine the trend for executions
- executionTrend := "neutral"
- executionTrendPercentage := 0.0
- if len(executionStats) > 1 {
- previousValue := executionStats[len(executionStats)-2].Value
- currentValue := executionStats[len(executionStats)-1].Value
- if previousValue != 0 {
- if currentValue > previousValue {
- executionTrend = "positive"
- executionTrendPercentage = (float64(currentValue-previousValue) / float64(previousValue)) * 100
- } else if currentValue < previousValue {
- executionTrend = "negative"
- executionTrendPercentage = (float64(previousValue-currentValue) / float64(previousValue)) * 100
- }
- } else if currentValue > 0 {
- executionTrend = "positive"
- executionTrendPercentage = float64(currentValue) * 100 // Reflect significant increase
+ weekday := time.Now().AddDate(0, 0, -i).Weekday().String()[:3]
+
+ executionStats = append(executionStats, Stats{
+ Weekday: weekday,
+ TotalExecutions: totalStatsMap[weekday],
+ Success: statsMap[weekday]["success"],
+ Error: statsMap[weekday]["error"],
+ Pending: statsMap[weekday]["pending"],
+ Running: statsMap[weekday]["running"],
+ Canceled: statsMap[weekday]["canceled"],
+ Scheduled: statsMap[weekday]["scheduled"],
+ NoPatternMatch: statsMap[weekday]["noPatternMatch"],
+ Recovered: statsMap[weekday]["recovered"],
+ })
+ }
+
+ // alerts - similar logic as executions
+ type RawAlertStats struct {
+ Date string `json:"date"`
+ Status string `json:"status"`
+ Value int `json:"value"`
+ }
+
+ var rawAlertStats []RawAlertStats
+ err = db.NewSelect().
+ TableExpr("(SELECT DATE(created_at) as date, status, COUNT(*) as value FROM alerts WHERE flow_id IN (?) AND created_at >= NOW() - INTERVAL '7 days' GROUP BY DATE(created_at), status) AS subquery", bun.In(flowsArray)).
+ Scan(context, &rawAlertStats)
+ if err != nil {
+ httperror.InternalServerError(context, "Error collecting alert stats from db", err)
+ return
+ }
+
+ // Create a map to store the alert stats by weekday and status
+ alertStatsMap := make(map[string]map[string]int)
+ totalAlertStatsMap := make(map[string]int)
+ for _, stat := range rawAlertStats {
+ date, _ := time.Parse("2006-01-02", stat.Date)
+ weekday := date.Weekday().String()[:3]
+
+ if alertStatsMap[weekday] == nil {
+ alertStatsMap[weekday] = make(map[string]int)
}
- executionTrendPercentage, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", executionTrendPercentage), 64)
+
+ alertStatsMap[weekday][stat.Status] += stat.Value
+ totalAlertStatsMap[weekday] += stat.Value
+ }
+
+ // Generate the alert stats for each weekday of the week
+ var alertStats []AlertStats
+ for i := 6; i >= 0; i-- { // Look from the current weekday in the past
+ weekday := time.Now().AddDate(0, 0, -i).Weekday().String()[:3]
+
+ alertStats = append(alertStats, AlertStats{
+ Weekday: weekday,
+ TotalAlerts: totalAlertStatsMap[weekday],
+ Firing: alertStatsMap[weekday]["firing"],
+ Resolved: alertStatsMap[weekday]["resolved"],
+ })
+ }
+
+ alertCount := 0
+ for _, alert := range alertStats {
+ alertCount += alert.TotalAlerts
}
executionCount := 0
for _, execution := range executionStats {
- executionCount += execution.Value
+ executionCount += execution.TotalExecutions
}
context.JSON(http.StatusOK, gin.H{"result": "success", "stats": gin.H{
- "total_projects": projectCount,
- "total_flows": flowCount,
- "total_runners": runnerCount,
- "total_executions": executionCount,
- "executions": executionStats,
- "execution_trend": executionTrend,
- "execution_trend_percentage": executionTrendPercentage,
+ "total_projects": projectCount,
+ "total_flows": flowCount,
+ "total_runners": runnerCount,
+ "total_executions": executionCount,
+ "total_alerts": alertCount,
+ "executions": executionStats,
+ "alerts": alertStats,
}})
}
diff --git a/services/frontend/components/dashboard/home.tsx b/services/frontend/components/dashboard/home.tsx
index 3c947f7d..9601f653 100644
--- a/services/frontend/components/dashboard/home.tsx
+++ b/services/frontend/components/dashboard/home.tsx
@@ -16,10 +16,11 @@ import { useEffect, useState } from "react";
import ReactTimeago from "react-timeago";
import WelcomeModal from "@/components/modals/user/welcome";
-import Stats from "@/components/dashboard/stats";
import Executions from "../executions/executions";
+import DashboardExecutionsStats from "./stats-charts";
+
export default function DashboardHome({
stats,
flows,
@@ -381,8 +382,7 @@ export default function DashboardHome({
- {/* Stats */}
-
+
Executions
diff --git a/services/frontend/components/dashboard/stats-charts.tsx b/services/frontend/components/dashboard/stats-charts.tsx
new file mode 100644
index 00000000..df45dcb1
--- /dev/null
+++ b/services/frontend/components/dashboard/stats-charts.tsx
@@ -0,0 +1,260 @@
+"use client";
+
+import type { ButtonProps, CardProps, RadioProps } from "@heroui/react";
+
+import React from "react";
+import {
+ BarChart,
+ Bar,
+ XAxis,
+ YAxis,
+ Tooltip,
+ ResponsiveContainer,
+} from "recharts";
+import { Card, Button, VisuallyHidden, useRadio, cn } from "@heroui/react";
+
+type ChartData = {
+ weekday: string;
+ [key: string]: string | number;
+};
+
+type BarChartProps = {
+ title: string;
+ categories: { title: string; color: string }[];
+ chartData: ChartData[];
+};
+
+export default function DashboardExecutionsStats({ stats }: { stats: any }) {
+ const data: BarChartProps[] = [
+ {
+ title: "Processed Executions",
+ categories: [
+ {
+ title: "Success",
+ color: "success",
+ },
+ {
+ title: "Error",
+ color: "danger",
+ },
+ {
+ title: "Pending",
+ color: "default",
+ },
+ {
+ title: "Running",
+ color: "primary",
+ },
+ {
+ title: "Canceled",
+ color: "danger-300",
+ },
+ {
+ title: "Scheduled",
+ color: "secondary",
+ },
+ {
+ title: "NoPatternMatch",
+ color: "secondary-300",
+ },
+ {
+ title: "Recovered",
+ color: "warning",
+ },
+ ],
+ chartData: stats.executions,
+ },
+ {
+ title: "Incoming Alerts",
+ categories: [
+ {
+ title: "Resolved",
+ color: "success",
+ },
+ {
+ title: "Firing",
+ color: "danger",
+ },
+ ],
+ chartData: stats.alerts,
+ },
+ ];
+
+ return (
+
+ {data.map((item, index) => (
+
+ ))}
+
+ );
+}
+
+const formatWeekday = (weekday: string) => {
+ const day =
+ {
+ Mon: 1,
+ Tue: 2,
+ Wed: 3,
+ Thu: 4,
+ Fri: 5,
+ Sat: 6,
+ Sun: 0,
+ }[weekday] ?? 0;
+
+ return new Intl.DateTimeFormat("en-US", { weekday: "long" }).format(
+ new Date(2024, 0, day),
+ );
+};
+
+const BarChartCard = React.forwardRef<
+ // eslint-disable-next-line no-undef
+ HTMLDivElement,
+ Omit & BarChartProps
+>(({ className, title, categories, chartData, ...props }, ref) => {
+ return (
+
+
+
+ {title}
+
+
+ {categories.map((category, index) => (
+
+
+ {category.title}
+
+ ))}
+
+
+
+
+
+
+ (
+
+
+
+ {formatWeekday(label)}
+
+ {payload?.map((p, index) => {
+ const name = p.name;
+ const value = p.value;
+ const category =
+ categories.find((c) => c.title.toLowerCase() === name) ??
+ name;
+
+ return (
+
+
+
+
+ {category.title}
+
+
+ {value}
+
+
+
+ );
+ })}
+
+
+ )}
+ cursor={false}
+ />
+ {categories.map((category, index) => (
+
+ ))}
+
+
+
+ );
+});
+
+BarChartCard.displayName = "BarChartCard";
+
+const ButtonRadioItem = React.forwardRef<
+ // eslint-disable-next-line no-undef
+ HTMLInputElement,
+ Omit & {
+ color?: ButtonProps["color"];
+ size?: ButtonProps["size"];
+ variant?: ButtonProps["variant"];
+ }
+>(({ children, color, size = "sm", variant, ...props }, ref) => {
+ const { Component, isSelected, getBaseProps, getInputProps } =
+ useRadio(props);
+
+ return (
+
+
+
+
+
+ {children}
+
+
+ );
+});
+
+ButtonRadioItem.displayName = "ButtonRadioItem";
diff --git a/services/frontend/components/dashboard/stats.tsx b/services/frontend/components/dashboard/stats.tsx
deleted file mode 100644
index f1d1d7f3..00000000
--- a/services/frontend/components/dashboard/stats.tsx
+++ /dev/null
@@ -1,232 +0,0 @@
-"use client";
-
-import { Icon } from "@iconify/react";
-import { Card, Chip } from "@heroui/react";
-import React from "react";
-import { Bar, BarChart, ResponsiveContainer, Tooltip, XAxis } from "recharts";
-
-import { cn } from "@/components/cn/cn";
-
-const formatWeekday = (weekday: string) => {
- if (weekday === "Mo") {
- return "Monday";
- } else if (weekday === "Tu") {
- return "Tuesday";
- } else if (weekday === "We") {
- return "Wednesday";
- } else if (weekday === "Th") {
- return "Thursday";
- } else if (weekday === "Fr") {
- return "Friday";
- } else if (weekday === "Sa") {
- return "Saturday";
- } else if (weekday === "Su") {
- return "Sunday";
- }
-};
-
-const formatValue = (value: number) => {
- return new Intl.NumberFormat("en-US", {
- style: "decimal",
- minimumFractionDigits: 0,
- maximumFractionDigits: 0,
- }).format(value);
-};
-
-export default function Stats({ stats }: { stats: any }) {
- const data = [
- {
- title: "Total Executions this week",
- value: stats.total_executions,
- change: `${stats.execution_trend_percentage}% today`,
- changeType: stats.execution_trend,
- trendChipPosition: "bottom",
- chartData: stats.executions,
- },
- ];
-
- const handleMouseEnter = React.useCallback(
- (chartIndex: number, itemIndex: number) => {
- // eslint-disable-next-line no-undef
- const bars = document.querySelectorAll(
- `#chart-${chartIndex} .recharts-bar-rectangle`,
- );
-
- bars.forEach((bar, i) => {
- if (i !== itemIndex) {
- const path = bar.querySelector("path");
-
- if (path) {
- path.setAttribute("fill", "hsl(var(--heroui-default-300))");
- }
- }
- });
- },
- [],
- );
-
- const handleMouseLeave = React.useCallback((chartIndex: number) => {
- // eslint-disable-next-line no-undef
- const bars = document.querySelectorAll(
- `#chart-${chartIndex} .recharts-bar-rectangle`,
- );
-
- bars.forEach((bar) => {
- const path = bar.querySelector("path");
-
- if (path) {
- path.setAttribute("fill", "hsl(var(--heroui-foreground))");
- }
- });
- }, []);
-
- const trendChipContent = React.useCallback(
- ({
- changeType,
- change,
- trendChipPosition,
- }: {
- changeType: string;
- change: string;
- trendChipPosition: string;
- }) => (
-
-
- ) : changeType === "neutral" ? (
-
- ) : (
-
- )
- }
- variant="flat"
- >
- {change}
-
-
- ),
- [],
- );
-
- return (
-
- {data.map(
- ({ title, value, changeType, change, trendChipPosition }, index) => (
-
-
-
-
-
- {title}
-
-
-
- {value}
-
- {trendChipContent({
- changeType,
- change,
- trendChipPosition,
- })}
-
-
-
- {trendChipContent({
- changeType,
- change,
- trendChipPosition,
- })}
-
-
-
-
-
-
-
-
- (
-
-
-
- {formatWeekday(label)}
-
-
- {formatValue(payload?.[0]?.value as number)}
-
-
- )}
- cursor={false}
- />
-
- handleMouseEnter(index, itemIndex)
- }
- onMouseLeave={() => handleMouseLeave(index)}
- />
-
-
-
-
-
- ),
- )}
-
- );
-}
From 285763d56f9af04f4f4ceb6ee442f33b237cce5b Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Mon, 8 Sep 2025 10:59:31 +0200
Subject: [PATCH 24/45] feat: refactor Alerts component to support multiple
flows and improve integration in Dashboard
---
services/frontend/app/alerts/page.tsx | 5 ++
.../frontend/components/alerts/alerts.tsx | 21 +++--
.../frontend/components/alerts/heading.tsx | 79 +------------------
services/frontend/components/alerts/list.tsx | 3 +-
.../components/alerts/page-client.tsx | 51 ++++++++++++
.../frontend/components/dashboard/home.tsx | 10 ++-
.../components/executions/executions.tsx | 6 +-
.../frontend/components/flows/flow/tabs.tsx | 3 +-
8 files changed, 89 insertions(+), 89 deletions(-)
create mode 100644 services/frontend/app/alerts/page.tsx
create mode 100644 services/frontend/components/alerts/page-client.tsx
diff --git a/services/frontend/app/alerts/page.tsx b/services/frontend/app/alerts/page.tsx
new file mode 100644
index 00000000..e3b30876
--- /dev/null
+++ b/services/frontend/app/alerts/page.tsx
@@ -0,0 +1,5 @@
+import AlertsPageClient from "@/components/alerts/page-client";
+
+export default function RunnersPage() {
+ return ;
+}
diff --git a/services/frontend/components/alerts/alerts.tsx b/services/frontend/components/alerts/alerts.tsx
index 396a35ef..b1df0cd3 100644
--- a/services/frontend/components/alerts/alerts.tsx
+++ b/services/frontend/components/alerts/alerts.tsx
@@ -23,12 +23,16 @@ import AlertsList from "./list";
export default function Alerts({
runners,
- flow,
+ flows,
canEdit,
+ flowID,
+ showFlow,
}: {
runners: any;
- flow?: any;
+ flows: any;
canEdit?: boolean;
+ flowID?: any;
+ showFlow?: boolean;
}) {
const { displayStyle, setDisplayStyle } = useAlertsStyleStore();
const [statusFilter, setStatusFilter] = useState(new Set([]) as any);
@@ -46,15 +50,15 @@ export default function Alerts({
// Always call both hooks but only use the relevant one
const flowAlertsResult = useFlowAlertsPaginated(
- flow.id || null,
+ flowID || null,
limit,
offset,
statusFilterString,
);
const allAlertsResult = useAlerts(
- flow.id ? 0 : limit,
- flow.id ? 0 : offset,
- flow.id ? null : statusFilterString,
+ flowID ? 0 : limit,
+ flowID ? 0 : offset,
+ flowID ? null : statusFilterString,
);
// Choose the right result based on whether we have a flowID
@@ -63,7 +67,7 @@ export default function Alerts({
total: totalAlerts,
isLoading: loading,
refresh,
- } = flow.id ? flowAlertsResult : allAlertsResult;
+ } = flowID ? flowAlertsResult : allAlertsResult;
const items = useMemo(() => {
return alerts || [];
@@ -180,9 +184,10 @@ export default function Alerts({
)}
>
diff --git a/services/frontend/components/alerts/heading.tsx b/services/frontend/components/alerts/heading.tsx
index be759dab..2ad5f1b7 100644
--- a/services/frontend/components/alerts/heading.tsx
+++ b/services/frontend/components/alerts/heading.tsx
@@ -1,83 +1,10 @@
-import { Card, CardBody, Spacer } from "@heroui/react";
-import { Icon } from "@iconify/react";
-import NumberFlow from "@number-flow/react";
+"use client";
-export default function AlertsHeading({ alerts }: any) {
+export default function AlertsHeading() {
return (
-
+
-
-
-
-
-
-
-
-
-
-
-
-
- alert.status === "firing")
- .length
- }
- />
-
-
Firing
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- alert.status === "resolved",
- ).length
- }
- />
-
-
Resolved
-
-
-
-
-
-
);
diff --git a/services/frontend/components/alerts/list.tsx b/services/frontend/components/alerts/list.tsx
index a71d2bd2..23bd37c2 100644
--- a/services/frontend/components/alerts/list.tsx
+++ b/services/frontend/components/alerts/list.tsx
@@ -45,8 +45,9 @@ export default function AlertsList({
{
setTargetAlert(alert);
alertDrawer.onOpenChange();
diff --git a/services/frontend/components/alerts/page-client.tsx b/services/frontend/components/alerts/page-client.tsx
new file mode 100644
index 00000000..25c1d9ea
--- /dev/null
+++ b/services/frontend/components/alerts/page-client.tsx
@@ -0,0 +1,51 @@
+"use client";
+
+import { Divider } from "@heroui/react";
+
+import ErrorCard from "@/components/error/ErrorCard";
+import { PageSkeleton } from "@/components/loading/page-skeleton";
+import { useUserDetails, useRunners, useFlows } from "@/lib/swr/hooks/flows";
+
+import Alerts from "./alerts";
+import AlertsHeading from "./heading";
+
+export default function AlertsPageClient() {
+ const {
+ runners,
+ isLoading: runnersLoading,
+ isError: runnersError,
+ } = useRunners();
+ const { flows, isLoading: flowsLoading, isError: flowsError } = useFlows();
+ const { user, isLoading: userLoading, isError: userError } = useUserDetails();
+
+ // Check if any essential data is still loading or missing
+ const isLoading =
+ runnersLoading || flowsLoading || userLoading || !runners || !user;
+
+ // Show loading state if essential data is still loading
+ if (isLoading) {
+ return ;
+ }
+
+ // Show error state
+ const hasError = runnersError || flowsError || userError;
+
+ if (hasError) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+ );
+}
diff --git a/services/frontend/components/dashboard/home.tsx b/services/frontend/components/dashboard/home.tsx
index 9601f653..fe74aa35 100644
--- a/services/frontend/components/dashboard/home.tsx
+++ b/services/frontend/components/dashboard/home.tsx
@@ -18,6 +18,7 @@ import ReactTimeago from "react-timeago";
import WelcomeModal from "@/components/modals/user/welcome";
import Executions from "../executions/executions";
+import Alerts from "../alerts/alerts";
import DashboardExecutionsStats from "./stats-charts";
@@ -385,8 +386,13 @@ export default function DashboardHome({
- Executions
-
+ Executions & Alerts
+
+
diff --git a/services/frontend/components/executions/executions.tsx b/services/frontend/components/executions/executions.tsx
index c4585d45..9feed576 100644
--- a/services/frontend/components/executions/executions.tsx
+++ b/services/frontend/components/executions/executions.tsx
@@ -30,6 +30,7 @@ import {
import ExecutionsList from "./executionsList";
import ExecutionsTable from "./executionsTable";
import ExecutionsCompact from "./executionsCompact";
+import NumberFlow from "@number-flow/react";
export default function Executions({
runners,
@@ -92,7 +93,10 @@ export default function Executions({
return (
-
+
+
+ Total Executions:
+
diff --git a/services/frontend/components/flows/flow/tabs.tsx b/services/frontend/components/flows/flow/tabs.tsx
index b03c069c..8ffdc787 100644
--- a/services/frontend/components/flows/flow/tabs.tsx
+++ b/services/frontend/components/flows/flow/tabs.tsx
@@ -126,7 +126,8 @@ export default function FlowTabs({
>
From e1be5d78301e32957cde33888234ad3c20e52403 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 8 Sep 2025 20:34:43 +0000
Subject: [PATCH 25/45] chore(deps): bump the backend group in
/services/backend with 2 updates
Bumps the backend group in /services/backend with 2 updates: [golang.org/x/crypto](https://github.com/golang/crypto) and [github.com/spf13/viper](https://github.com/spf13/viper).
Updates `golang.org/x/crypto` from 0.41.0 to 0.42.0
- [Commits](https://github.com/golang/crypto/compare/v0.41.0...v0.42.0)
Updates `github.com/spf13/viper` from 1.20.1 to 1.21.0
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.20.1...v1.21.0)
---
updated-dependencies:
- dependency-name: golang.org/x/crypto
dependency-version: 0.42.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: backend
- dependency-name: github.com/spf13/viper
dependency-version: 1.21.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: backend
...
Signed-off-by: dependabot[bot]
---
services/backend/go.mod | 27 +++++++++----------
services/backend/go.sum | 58 ++++++++++++++++++++---------------------
2 files changed, 41 insertions(+), 44 deletions(-)
diff --git a/services/backend/go.mod b/services/backend/go.mod
index 2e50c958..70593f5b 100644
--- a/services/backend/go.mod
+++ b/services/backend/go.mod
@@ -6,7 +6,7 @@ require (
github.com/uptrace/bun v1.2.15
github.com/uptrace/bun/driver/pgdriver v1.2.15
github.com/uptrace/bun/extra/bunotel v1.2.15
- golang.org/x/crypto v0.41.0
+ golang.org/x/crypto v0.42.0
)
require (
@@ -14,7 +14,7 @@ require (
github.com/bytedance/sonic v1.13.3 // indirect
github.com/bytedance/sonic/loader v0.2.4 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect
- github.com/fsnotify/fsnotify v1.8.0 // indirect
+ github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
github.com/gin-contrib/sse v1.1.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
@@ -22,7 +22,7 @@ require (
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.26.0 // indirect
- github.com/go-viper/mapstructure/v2 v2.3.0 // indirect
+ github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
@@ -33,11 +33,11 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect
- github.com/sagikazarmark/locafero v0.7.0 // indirect
- github.com/sourcegraph/conc v0.3.0 // indirect
- github.com/spf13/afero v1.12.0 // indirect
- github.com/spf13/cast v1.7.1 // indirect
- github.com/spf13/pflag v1.0.6 // indirect
+ github.com/sagikazarmark/locafero v0.11.0 // indirect
+ github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
+ github.com/spf13/afero v1.15.0 // indirect
+ github.com/spf13/cast v1.10.0 // indirect
+ github.com/spf13/pflag v1.0.10 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
@@ -50,11 +50,10 @@ require (
go.opentelemetry.io/otel v1.37.0 // indirect
go.opentelemetry.io/otel/metric v1.37.0 // indirect
go.opentelemetry.io/otel/trace v1.37.0 // indirect
- go.uber.org/atomic v1.10.0 // indirect
- go.uber.org/multierr v1.9.0 // indirect
+ go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/arch v0.18.0 // indirect
- golang.org/x/net v0.42.0 // indirect
- golang.org/x/text v0.28.0 // indirect
+ golang.org/x/net v0.43.0 // indirect
+ golang.org/x/text v0.29.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
mellium.im/sasl v0.3.2 // indirect
@@ -71,8 +70,8 @@ require (
github.com/mattn/go-sqlite3 v1.14.32
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/sirupsen/logrus v1.9.3
- github.com/spf13/viper v1.20.1
+ github.com/spf13/viper v1.21.0
github.com/uptrace/bun/dialect/pgdialect v1.2.15
github.com/v1Flows/shared-library v1.0.27
- golang.org/x/sys v0.35.0 // indirect
+ golang.org/x/sys v0.36.0 // indirect
)
diff --git a/services/backend/go.sum b/services/backend/go.sum
index 6b410a87..c87e3d22 100644
--- a/services/backend/go.sum
+++ b/services/backend/go.sum
@@ -17,8 +17,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
-github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
-github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
+github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
+github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
github.com/gin-contrib/cors v1.7.6 h1:3gQ8GMzs1Ylpf70y8bMw4fVpycXIeX1ZemuSQIsnQQY=
@@ -40,8 +40,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
-github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk=
-github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
+github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
+github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
@@ -86,20 +86,20 @@ github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++
github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
-github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
-github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
+github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
+github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
-github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
-github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
-github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
-github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
-github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
-github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
-github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
-github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
-github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
+github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
+github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
+github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
+github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
+github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
+github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
+github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
+github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
+github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -111,8 +111,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
-github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
+github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
@@ -147,22 +147,20 @@ go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/Wgbsd
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
-go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
-go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
-go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
-go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
+go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
+go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/arch v0.18.0 h1:WN9poc33zL4AzGxqf8VtpKUnGvMi8O9lhNyBMF/85qc=
golang.org/x/arch v0.18.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
-golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
-golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
-golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
-golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
+golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
+golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
+golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
+golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
-golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
-golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
-golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
+golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
+golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
+golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
From f545985376c26630edd50d28ede989253b7cb494 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 8 Sep 2025 21:12:50 +0000
Subject: [PATCH 26/45] chore(deps): bump next from 15.3.3 to 15.5.2 in
/services/frontend
Bumps [next](https://github.com/vercel/next.js) from 15.3.3 to 15.5.2.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v15.3.3...v15.5.2)
---
updated-dependencies:
- dependency-name: next
dependency-version: 15.5.2
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
services/frontend/package.json | 2 +-
services/frontend/pnpm-lock.yaml | 178 +++++++++++++++----------------
2 files changed, 86 insertions(+), 94 deletions(-)
diff --git a/services/frontend/package.json b/services/frontend/package.json
index 9fd9189c..6ebe08cf 100644
--- a/services/frontend/package.json
+++ b/services/frontend/package.json
@@ -71,7 +71,7 @@
"lodash": "^4.17.21",
"lucide-react": "^0.536.0",
"match-sorter": "^8.0.0",
- "next": "15.3.3",
+ "next": "15.5.2",
"next-pwa": "^5.6.0",
"next-themes": "^0.4.6",
"postcss": "8.5.6",
diff --git a/services/frontend/pnpm-lock.yaml b/services/frontend/pnpm-lock.yaml
index 4cc50033..ad5edc9e 100644
--- a/services/frontend/pnpm-lock.yaml
+++ b/services/frontend/pnpm-lock.yaml
@@ -79,7 +79,7 @@ importers:
version: 3.10.8(react@19.0.0)
'@serwist/next':
specifier: ^9.0.12
- version: 9.0.12(next@15.3.3(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(typescript@5.7.3)(webpack@5.98.0)
+ version: 9.0.12(next@15.5.2(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(typescript@5.7.3)(webpack@5.98.0)
'@tabler/icons-react':
specifier: ^3.33.0
version: 3.33.0(react@19.0.0)
@@ -192,11 +192,11 @@ importers:
specifier: ^8.0.0
version: 8.0.0
next:
- specifier: 15.3.3
- version: 15.3.3(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ specifier: 15.5.2
+ version: 15.5.2(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
next-pwa:
specifier: ^5.6.0
- version: 5.6.0(@babel/core@7.26.10)(next@15.3.3(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(webpack@5.98.0)
+ version: 5.6.0(@babel/core@7.26.10)(next@15.5.2(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(webpack@5.98.0)
next-themes:
specifier: ^0.4.6
version: 0.4.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
@@ -460,8 +460,8 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
- '@babel/parser@7.28.3':
- resolution: {integrity: sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==}
+ '@babel/parser@7.28.4':
+ resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -850,8 +850,8 @@ packages:
resolution: {integrity: sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==}
engines: {node: '>=6.9.0'}
- '@babel/types@7.28.2':
- resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==}
+ '@babel/types@7.28.4':
+ resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==}
engines: {node: '>=6.9.0'}
'@clack/core@0.4.1':
@@ -984,8 +984,8 @@ packages:
'@emnapi/core@1.4.5':
resolution: {integrity: sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==}
- '@emnapi/runtime@1.4.5':
- resolution: {integrity: sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==}
+ '@emnapi/runtime@1.5.0':
+ resolution: {integrity: sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==}
'@emnapi/wasi-threads@1.0.1':
resolution: {integrity: sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==}
@@ -1971,8 +1971,8 @@ packages:
'@napi-rs/wasm-runtime@0.2.8':
resolution: {integrity: sha512-OBlgKdX7gin7OIq4fadsjpg+cp2ZphvAIKucHsNfTdJiqdOmOEwQd/bHi0VwNrcw5xpBJyUw6cK/QilCqy1BSg==}
- '@next/env@15.3.3':
- resolution: {integrity: sha512-OdiMrzCl2Xi0VTjiQQUK0Xh7bJHnOuET2s+3V+Y40WJBAXrJeGA3f+I8MZJ/YQ3mVGi5XGR1L66oFlgqXhQ4Vw==}
+ '@next/env@15.5.2':
+ resolution: {integrity: sha512-Qe06ew4zt12LeO6N7j8/nULSOe3fMXE4dM6xgpBQNvdzyK1sv5y4oAP3bq4LamrvGCZtmRYnW8URFCeX5nFgGg==}
'@next/eslint-plugin-next@15.4.6':
resolution: {integrity: sha512-2NOu3ln+BTcpnbIDuxx6MNq+pRrCyey4WSXGaJIyt0D2TYicHeO9QrUENNjcf673n3B1s7hsiV5xBYRCK1Q8kA==}
@@ -1980,50 +1980,50 @@ packages:
'@next/eslint-plugin-next@15.4.7':
resolution: {integrity: sha512-asj3RRiEruRLVr+k2ZC4hll9/XBzegMpFMr8IIRpNUYypG86m/a76339X2WETl1C53A512w2INOc2KZV769KPA==}
- '@next/swc-darwin-arm64@15.3.3':
- resolution: {integrity: sha512-WRJERLuH+O3oYB4yZNVahSVFmtxRNjNF1I1c34tYMoJb0Pve+7/RaLAJJizyYiFhjYNGHRAE1Ri2Fd23zgDqhg==}
+ '@next/swc-darwin-arm64@15.5.2':
+ resolution: {integrity: sha512-8bGt577BXGSd4iqFygmzIfTYizHb0LGWqH+qgIF/2EDxS5JsSdERJKA8WgwDyNBZgTIIA4D8qUtoQHmxIIquoQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
- '@next/swc-darwin-x64@15.3.3':
- resolution: {integrity: sha512-XHdzH/yBc55lu78k/XwtuFR/ZXUTcflpRXcsu0nKmF45U96jt1tsOZhVrn5YH+paw66zOANpOnFQ9i6/j+UYvw==}
+ '@next/swc-darwin-x64@15.5.2':
+ resolution: {integrity: sha512-2DjnmR6JHK4X+dgTXt5/sOCu/7yPtqpYt8s8hLkHFK3MGkka2snTv3yRMdHvuRtJVkPwCGsvBSwmoQCHatauFQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
- '@next/swc-linux-arm64-gnu@15.3.3':
- resolution: {integrity: sha512-VZ3sYL2LXB8znNGcjhocikEkag/8xiLgnvQts41tq6i+wql63SMS1Q6N8RVXHw5pEUjiof+II3HkDd7GFcgkzw==}
+ '@next/swc-linux-arm64-gnu@15.5.2':
+ resolution: {integrity: sha512-3j7SWDBS2Wov/L9q0mFJtEvQ5miIqfO4l7d2m9Mo06ddsgUK8gWfHGgbjdFlCp2Ek7MmMQZSxpGFqcC8zGh2AA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@next/swc-linux-arm64-musl@15.3.3':
- resolution: {integrity: sha512-h6Y1fLU4RWAp1HPNJWDYBQ+e3G7sLckyBXhmH9ajn8l/RSMnhbuPBV/fXmy3muMcVwoJdHL+UtzRzs0nXOf9SA==}
+ '@next/swc-linux-arm64-musl@15.5.2':
+ resolution: {integrity: sha512-s6N8k8dF9YGc5T01UPQ08yxsK6fUow5gG1/axWc1HVVBYQBgOjca4oUZF7s4p+kwhkB1bDSGR8QznWrFZ/Rt5g==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@next/swc-linux-x64-gnu@15.3.3':
- resolution: {integrity: sha512-jJ8HRiF3N8Zw6hGlytCj5BiHyG/K+fnTKVDEKvUCyiQ/0r5tgwO7OgaRiOjjRoIx2vwLR+Rz8hQoPrnmFbJdfw==}
+ '@next/swc-linux-x64-gnu@15.5.2':
+ resolution: {integrity: sha512-o1RV/KOODQh6dM6ZRJGZbc+MOAHww33Vbs5JC9Mp1gDk8cpEO+cYC/l7rweiEalkSm5/1WGa4zY7xrNwObN4+Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@next/swc-linux-x64-musl@15.3.3':
- resolution: {integrity: sha512-HrUcTr4N+RgiiGn3jjeT6Oo208UT/7BuTr7K0mdKRBtTbT4v9zJqCDKO97DUqqoBK1qyzP1RwvrWTvU6EPh/Cw==}
+ '@next/swc-linux-x64-musl@15.5.2':
+ resolution: {integrity: sha512-/VUnh7w8RElYZ0IV83nUcP/J4KJ6LLYliiBIri3p3aW2giF+PAVgZb6mk8jbQSB3WlTai8gEmCAr7kptFa1H6g==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@next/swc-win32-arm64-msvc@15.3.3':
- resolution: {integrity: sha512-SxorONgi6K7ZUysMtRF3mIeHC5aA3IQLmKFQzU0OuhuUYwpOBc1ypaLJLP5Bf3M9k53KUUUj4vTPwzGvl/NwlQ==}
+ '@next/swc-win32-arm64-msvc@15.5.2':
+ resolution: {integrity: sha512-sMPyTvRcNKXseNQ/7qRfVRLa0VhR0esmQ29DD6pqvG71+JdVnESJaHPA8t7bc67KD5spP3+DOCNLhqlEI2ZgQg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
- '@next/swc-win32-x64-msvc@15.3.3':
- resolution: {integrity: sha512-4QZG6F8enl9/S2+yIiOiju0iCTFd93d8VC1q9LZS4p/Xuk81W2QDjCFeoogmrWWkAD59z8ZxepBQap2dKS5ruw==}
+ '@next/swc-win32-x64-msvc@15.5.2':
+ resolution: {integrity: sha512-W5VvyZHnxG/2ukhZF/9Ikdra5fdNftxI6ybeVKYvBPDtyx7x4jPPSNduUkfH5fo3zG0JQ0bPxgy41af2JX5D4Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@@ -3008,9 +3008,6 @@ packages:
'@surma/rollup-plugin-off-main-thread@2.2.3':
resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==}
- '@swc/counter@0.1.3':
- resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
-
'@swc/helpers@0.5.15':
resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
@@ -3992,10 +3989,6 @@ packages:
resolution: {integrity: sha512-p1n8zyCkt1BVrKNFymOHjcDSAl7oq/gUvfgULv2EblgpPVQlQr9yHnWjg9IJ2MhfwPqiYqMMrr01OY7yQoK2yA==}
engines: {node: '>=18.20'}
- busboy@1.6.0:
- resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
- engines: {node: '>=10.16.0'}
-
cac@6.7.14:
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
engines: {node: '>=8'}
@@ -4019,8 +4012,8 @@ packages:
caniuse-lite@1.0.30001709:
resolution: {integrity: sha512-NgL3vUTnDrPCZ3zTahp4fsugQ4dc7EKTSzwQDPEel6DMoMnfH2jhry9n2Zm8onbSR+f/QtKHFOA+iAQu4kbtWA==}
- caniuse-lite@1.0.30001731:
- resolution: {integrity: sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==}
+ caniuse-lite@1.0.30001741:
+ resolution: {integrity: sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==}
ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
@@ -5604,6 +5597,9 @@ packages:
magic-string@0.30.17:
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
+ magic-string@0.30.19:
+ resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==}
+
make-dir@3.1.0:
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
engines: {node: '>=8'}
@@ -5844,13 +5840,13 @@ packages:
react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
- next@15.3.3:
- resolution: {integrity: sha512-JqNj29hHNmCLtNvd090SyRbXJiivQ+58XjCcrC50Crb5g5u2zi7Y2YivbsEfzk6AtVI80akdOQbaMZwWB1Hthw==}
+ next@15.5.2:
+ resolution: {integrity: sha512-H8Otr7abj1glFhbGnvUt3gz++0AF1+QoCXEBmd/6aKbfdFwrn0LpA836Ed5+00va/7HQSDD+mOoVhn3tNy3e/Q==}
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
hasBin: true
peerDependencies:
'@opentelemetry/api': ^1.1.0
- '@playwright/test': ^1.41.2
+ '@playwright/test': ^1.51.1
babel-plugin-react-compiler: '*'
react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
@@ -6577,10 +6573,6 @@ packages:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'}
- streamsearch@1.1.0:
- resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
- engines: {node: '>=10.0.0'}
-
string-ts@2.2.1:
resolution: {integrity: sha512-Q2u0gko67PLLhbte5HmPfdOjNvUKbKQM+mCNQae6jE91DmoFHY6HH9GcdqCeNx87DZ2KKjiFxmA0R/42OneGWw==}
@@ -6729,6 +6721,10 @@ packages:
resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==}
engines: {node: '>=6'}
+ tapable@2.2.3:
+ resolution: {integrity: sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==}
+ engines: {node: '>=6'}
+
tar@7.4.3:
resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==}
engines: {node: '>=18'}
@@ -7419,9 +7415,9 @@ snapshots:
dependencies:
'@babel/types': 7.26.10
- '@babel/parser@7.28.3':
+ '@babel/parser@7.28.4':
dependencies:
- '@babel/types': 7.28.2
+ '@babel/types': 7.28.4
'@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.10)':
dependencies:
@@ -7908,7 +7904,7 @@ snapshots:
'@babel/helper-string-parser': 7.25.9
'@babel/helper-validator-identifier': 7.25.9
- '@babel/types@7.28.2':
+ '@babel/types@7.28.4':
dependencies:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.27.1
@@ -8214,7 +8210,7 @@ snapshots:
tslib: 2.8.1
optional: true
- '@emnapi/runtime@1.4.5':
+ '@emnapi/runtime@1.5.0':
dependencies:
tslib: 2.8.1
optional: true
@@ -9578,7 +9574,7 @@ snapshots:
'@img/sharp-wasm32@0.34.3':
dependencies:
- '@emnapi/runtime': 1.4.5
+ '@emnapi/runtime': 1.5.0
optional: true
'@img/sharp-win32-arm64@0.34.3':
@@ -9596,7 +9592,7 @@ snapshots:
'@internationalized/message@3.1.6':
dependencies:
- '@swc/helpers': 0.5.17
+ '@swc/helpers': 0.5.15
intl-messageformat: 10.7.16
'@internationalized/message@3.1.8':
@@ -9606,7 +9602,7 @@ snapshots:
'@internationalized/number@3.6.0':
dependencies:
- '@swc/helpers': 0.5.17
+ '@swc/helpers': 0.5.15
'@internationalized/number@3.6.4':
dependencies:
@@ -9614,7 +9610,7 @@ snapshots:
'@internationalized/string@3.2.5':
dependencies:
- '@swc/helpers': 0.5.17
+ '@swc/helpers': 0.5.15
'@internationalized/string@3.2.7':
dependencies:
@@ -9766,18 +9762,18 @@ snapshots:
'@napi-rs/wasm-runtime@0.2.12':
dependencies:
'@emnapi/core': 1.4.5
- '@emnapi/runtime': 1.4.5
+ '@emnapi/runtime': 1.5.0
'@tybys/wasm-util': 0.10.0
optional: true
'@napi-rs/wasm-runtime@0.2.8':
dependencies:
'@emnapi/core': 1.4.0
- '@emnapi/runtime': 1.4.5
+ '@emnapi/runtime': 1.5.0
'@tybys/wasm-util': 0.9.0
optional: true
- '@next/env@15.3.3': {}
+ '@next/env@15.5.2': {}
'@next/eslint-plugin-next@15.4.6':
dependencies:
@@ -9787,28 +9783,28 @@ snapshots:
dependencies:
fast-glob: 3.3.1
- '@next/swc-darwin-arm64@15.3.3':
+ '@next/swc-darwin-arm64@15.5.2':
optional: true
- '@next/swc-darwin-x64@15.3.3':
+ '@next/swc-darwin-x64@15.5.2':
optional: true
- '@next/swc-linux-arm64-gnu@15.3.3':
+ '@next/swc-linux-arm64-gnu@15.5.2':
optional: true
- '@next/swc-linux-arm64-musl@15.3.3':
+ '@next/swc-linux-arm64-musl@15.5.2':
optional: true
- '@next/swc-linux-x64-gnu@15.3.3':
+ '@next/swc-linux-x64-gnu@15.5.2':
optional: true
- '@next/swc-linux-x64-musl@15.3.3':
+ '@next/swc-linux-x64-musl@15.5.2':
optional: true
- '@next/swc-win32-arm64-msvc@15.3.3':
+ '@next/swc-win32-arm64-msvc@15.5.2':
optional: true
- '@next/swc-win32-x64-msvc@15.3.3':
+ '@next/swc-win32-x64-msvc@15.5.2':
optional: true
'@nodelib/fs.scandir@2.1.5':
@@ -11027,14 +11023,14 @@ snapshots:
optionalDependencies:
typescript: 5.7.3
- '@serwist/next@9.0.12(next@15.3.3(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(typescript@5.7.3)(webpack@5.98.0)':
+ '@serwist/next@9.0.12(next@15.5.2(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(typescript@5.7.3)(webpack@5.98.0)':
dependencies:
'@serwist/build': 9.0.12(typescript@5.7.3)
'@serwist/webpack-plugin': 9.0.12(typescript@5.7.3)(webpack@5.98.0)
'@serwist/window': 9.0.12(typescript@5.7.3)
chalk: 5.4.1
glob: 10.4.5
- next: 15.3.3(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ next: 15.5.2(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
serwist: 9.0.12(typescript@5.7.3)
zod: 3.24.2
optionalDependencies:
@@ -11077,8 +11073,6 @@ snapshots:
magic-string: 0.25.9
string.prototype.matchall: 4.0.12
- '@swc/counter@0.1.3': {}
-
'@swc/helpers@0.5.15':
dependencies:
tslib: 2.8.1
@@ -11843,7 +11837,7 @@ snapshots:
'@vue/compiler-core@3.5.13':
dependencies:
- '@babel/parser': 7.28.3
+ '@babel/parser': 7.28.4
'@vue/shared': 3.5.13
entities: 4.5.0
estree-walker: 2.0.2
@@ -11856,13 +11850,13 @@ snapshots:
'@vue/compiler-sfc@3.5.13':
dependencies:
- '@babel/parser': 7.28.3
+ '@babel/parser': 7.28.4
'@vue/compiler-core': 3.5.13
'@vue/compiler-dom': 3.5.13
'@vue/compiler-ssr': 3.5.13
'@vue/shared': 3.5.13
estree-walker: 2.0.2
- magic-string: 0.30.17
+ magic-string: 0.30.19
postcss: 8.5.6
source-map-js: 1.2.1
@@ -12191,10 +12185,6 @@ snapshots:
builtin-modules@4.0.0: {}
- busboy@1.6.0:
- dependencies:
- streamsearch: 1.1.0
-
cac@6.7.14: {}
call-bind-apply-helpers@1.0.2:
@@ -12218,7 +12208,7 @@ snapshots:
caniuse-lite@1.0.30001709: {}
- caniuse-lite@1.0.30001731: {}
+ caniuse-lite@1.0.30001741: {}
ccount@2.0.1: {}
@@ -14102,6 +14092,10 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
+ magic-string@0.30.19:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+
make-dir@3.1.0:
dependencies:
semver: 6.3.1
@@ -14527,12 +14521,12 @@ snapshots:
neo-async@2.6.2: {}
- next-pwa@5.6.0(@babel/core@7.26.10)(next@15.3.3(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(webpack@5.98.0):
+ next-pwa@5.6.0(@babel/core@7.26.10)(next@15.5.2(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(webpack@5.98.0):
dependencies:
babel-loader: 8.4.1(@babel/core@7.26.10)(webpack@5.98.0)
clean-webpack-plugin: 4.0.0(webpack@5.98.0)
globby: 11.1.0
- next: 15.3.3(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ next: 15.5.2(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
terser-webpack-plugin: 5.3.14(webpack@5.98.0)
workbox-webpack-plugin: 6.6.0(webpack@5.98.0)
workbox-window: 6.6.0
@@ -14550,26 +14544,24 @@ snapshots:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- next@15.3.3(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
+ next@15.5.2(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
dependencies:
- '@next/env': 15.3.3
- '@swc/counter': 0.1.3
+ '@next/env': 15.5.2
'@swc/helpers': 0.5.15
- busboy: 1.6.0
- caniuse-lite: 1.0.30001731
+ caniuse-lite: 1.0.30001741
postcss: 8.4.31
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
styled-jsx: 5.1.6(@babel/core@7.26.10)(react@19.0.0)
optionalDependencies:
- '@next/swc-darwin-arm64': 15.3.3
- '@next/swc-darwin-x64': 15.3.3
- '@next/swc-linux-arm64-gnu': 15.3.3
- '@next/swc-linux-arm64-musl': 15.3.3
- '@next/swc-linux-x64-gnu': 15.3.3
- '@next/swc-linux-x64-musl': 15.3.3
- '@next/swc-win32-arm64-msvc': 15.3.3
- '@next/swc-win32-x64-msvc': 15.3.3
+ '@next/swc-darwin-arm64': 15.5.2
+ '@next/swc-darwin-x64': 15.5.2
+ '@next/swc-linux-arm64-gnu': 15.5.2
+ '@next/swc-linux-arm64-musl': 15.5.2
+ '@next/swc-linux-x64-gnu': 15.5.2
+ '@next/swc-linux-x64-musl': 15.5.2
+ '@next/swc-win32-arm64-msvc': 15.5.2
+ '@next/swc-win32-x64-msvc': 15.5.2
sharp: 0.34.3
transitivePeerDependencies:
- '@babel/core'
@@ -15409,8 +15401,6 @@ snapshots:
es-errors: 1.3.0
internal-slot: 1.1.0
- streamsearch@1.1.0: {}
-
string-ts@2.2.1: {}
string-width@4.2.3:
@@ -15570,6 +15560,8 @@ snapshots:
tapable@2.2.2: {}
+ tapable@2.2.3: {}
+
tar@7.4.3:
dependencies:
'@isaacs/fs-minipass': 4.0.1
@@ -15955,7 +15947,7 @@ snapshots:
mime-types: 2.1.35
neo-async: 2.6.2
schema-utils: 4.3.2
- tapable: 2.2.2
+ tapable: 2.2.3
terser-webpack-plugin: 5.3.14(webpack@5.98.0)
watchpack: 2.4.4
webpack-sources: 3.3.3
From 37e47058b899984ac17a0e8a18752f08f2551466 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Tue, 9 Sep 2025 11:15:52 +0200
Subject: [PATCH 27/45] feat: enhance flow update functionality to include
patterns and alert settings
---
services/backend/handlers/flows/update.go | 4 +
.../components/executions/executions.tsx | 2 +-
.../components/flows/flow/settings.tsx | 277 +++++++++++++-----
.../frontend/components/flows/flow/tabs.tsx | 34 +--
.../frontend/components/modals/flows/edit.tsx | 4 +
.../frontend/lib/fetch/flow/PUT/UpdateFlow.ts | 2 +
6 files changed, 237 insertions(+), 86 deletions(-)
diff --git a/services/backend/handlers/flows/update.go b/services/backend/handlers/flows/update.go
index 6ac62580..4a10d314 100644
--- a/services/backend/handlers/flows/update.go
+++ b/services/backend/handlers/flows/update.go
@@ -3,6 +3,7 @@ package flows
import (
"errors"
"net/http"
+ "reflect"
"time"
"github.com/v1Flows/exFlow/services/backend/functions/gatekeeper"
@@ -92,6 +93,9 @@ func UpdateFlow(context *gin.Context, db *bun.DB) {
if flow.ScheduleEveryUnit != flowDB.ScheduleEveryUnit {
columns = append(columns, "schedule_every_unit")
}
+ if !reflect.DeepEqual(flow.Patterns, flowDB.Patterns) {
+ columns = append(columns, "patterns")
+ }
columns = append(columns, "exec_parallel")
columns = append(columns, "failure_pipeline_id")
columns = append(columns, "updated_at")
diff --git a/services/frontend/components/executions/executions.tsx b/services/frontend/components/executions/executions.tsx
index 9feed576..2e9b1468 100644
--- a/services/frontend/components/executions/executions.tsx
+++ b/services/frontend/components/executions/executions.tsx
@@ -14,6 +14,7 @@ import {
} from "@heroui/react";
import { Icon } from "@iconify/react";
import { useMemo, useState } from "react";
+import NumberFlow from "@number-flow/react";
import { useExecutionsStyleStore } from "@/lib/functions/userExecutionsStyle";
import {
@@ -30,7 +31,6 @@ import {
import ExecutionsList from "./executionsList";
import ExecutionsTable from "./executionsTable";
import ExecutionsCompact from "./executionsCompact";
-import NumberFlow from "@number-flow/react";
export default function Executions({
runners,
diff --git a/services/frontend/components/flows/flow/settings.tsx b/services/frontend/components/flows/flow/settings.tsx
index 5aa125af..78a22bf8 100644
--- a/services/frontend/components/flows/flow/settings.tsx
+++ b/services/frontend/components/flows/flow/settings.tsx
@@ -10,13 +10,19 @@ import {
SelectItem,
Spacer,
Switch,
+ Table,
+ TableBody,
+ TableCell,
+ TableColumn,
+ TableHeader,
+ TableRow,
} from "@heroui/react";
-import { useRouter } from "next/navigation";
import { useState } from "react";
import { Icon } from "@iconify/react";
import UpdateFlow from "@/lib/fetch/flow/PUT/UpdateFlow";
import ErrorCard from "@/components/error/ErrorCard";
+import { useRefreshCache } from "@/lib/swr/hooks/useRefreshCache";
export default function FlowSettings({
flow,
@@ -27,7 +33,7 @@ export default function FlowSettings({
user: any;
canEdit: boolean;
}) {
- const router = useRouter();
+ const { refreshFlowData } = useRefreshCache();
const [execParallel, setExecParallel] = useState(flow.exec_parallel);
const [failurePipelineID, setFailurePipelineID] = useState(
@@ -44,6 +50,7 @@ export default function FlowSettings({
flow.group_alerts_identifier,
);
const [alertThreshold, setAlertThreshold] = useState(flow.alert_threshold);
+ const [flowPatterns, setFlowPatterns] = useState(flow.patterns);
const [error, setError] = useState(false);
const [errorMessage, setErrorMessage] = useState("");
@@ -63,6 +70,7 @@ export default function FlowSettings({
groupAlerts,
groupAlertsIdentifier,
alertThreshold,
+ flowPatterns,
)) as any;
if (!response) {
@@ -73,7 +81,7 @@ export default function FlowSettings({
}
if (response.success) {
- router.refresh();
+ refreshFlowData(flow.id);
addToast({
title: "Flow",
description: "Flow updated successfully",
@@ -95,77 +103,210 @@ export default function FlowSettings({
return (
<>
{error && }
-
-
+
+
Actions
-
-
-
-
-
Execution Strategy
-
- Switch between parallel and sequential execution of
- actions
-
-
- {
- if (e.currentKey === "parallel") {
- setExecParallel(true);
- } else {
- setExecParallel(false);
+
+
+
+
+
+
Execution Strategy
+
+ Switch between parallel and sequential execution of
+ actions
+
+
+
- Sequential
- Parallel
-
-
-
+ placeholder="Select the execution strategy"
+ selectedKeys={[execParallel ? "parallel" : "sequential"]}
+ variant="bordered"
+ onSelectionChange={(e) => {
+ if (e.currentKey === "parallel") {
+ setExecParallel(true);
+ } else {
+ setExecParallel(false);
+ }
+ }}
+ >
+
Sequential
+
Parallel
+
+
+
-
-
-
-
Common Failure Pipeline
-
- Execute an failure pipeline when actions during an
- execution fail.
-
-
- CAUTION! This will override the per action failure
- pipeline
-
-
-
- {
- if (e.currentKey === "none") {
- setFailurePipelineID("");
- } else {
- setFailurePipelineID(e.currentKey);
+
+
+
+
+ Common Failure Pipeline
+
+
+ Execute an failure pipeline when actions during an
+ execution fail.
+
+
+ CAUTION! This will override the per action failure
+ pipeline
+
+
+
+ {
+ if (e.currentKey === "none") {
+ setFailurePipelineID("");
+ } else {
+ setFailurePipelineID(e.currentKey);
+ }
+ }}
+ >
+ None
+ {flow.failure_pipelines.map((pipeline: any) => (
+
+ {pipeline.name}
+
+ ))}
+
+
+
+
+
+ {flow.type == "alert" && (
+
+
+
+
Patterns
+
+ Patterns can be used to trigger executions only when the
+ alert payload contains specified key value pairs.
+
+
+
+ }
+ variant="flat"
+ onPress={() => {
+ const newPatterns = [...flowPatterns];
+
+ newPatterns.push({
+ key: "",
+ type: "equals",
+ value: "",
+ });
+ setFlowPatterns(newPatterns);
+ }}
+ />
+
+
+
+ )}
diff --git a/services/frontend/components/flows/flow/tabs.tsx b/services/frontend/components/flows/flow/tabs.tsx
index 8ffdc787..224b16bb 100644
--- a/services/frontend/components/flows/flow/tabs.tsx
+++ b/services/frontend/components/flows/flow/tabs.tsx
@@ -22,7 +22,7 @@ export default function FlowTabs({
members,
settings,
}: any) {
- const [selected, setSelected] = React.useState("actions");
+ const [selected, setSelected] = React.useState("executions");
const router = useRouter();
const pathname = usePathname();
@@ -30,7 +30,7 @@ export default function FlowTabs({
const params = new URLSearchParams(searchParams.toString());
React.useEffect(() => {
- const tab = params.get("tab") || "actions";
+ const tab = params.get("tab") || "executions";
setSelected(tab);
}, [params]);
@@ -60,6 +60,21 @@ export default function FlowTabs({
selectedKey={selected}
onSelectionChange={handleTabChange}
>
+
+
+ Executions
+
+ }
+ >
+
+
-
-
- Executions
-
- }
- >
-
-
{flow.type === "alert" && (
{
try {
const cookieStore = await cookies();
@@ -57,6 +58,7 @@ export default async function UpdateFlow(
group_alerts: groupAlerts,
group_alerts_identifier: groupAlertsIdentifier,
alert_threshold: alertThreshold,
+ patterns,
}),
},
);
From dffcde8a76a60d82f77431a5d6da72429596e559 Mon Sep 17 00:00:00 2001
From: Justin Neubert
Date: Tue, 9 Sep 2025 11:21:29 +0200
Subject: [PATCH 28/45] fix: update category assignment in BarChartCard to
handle missing categories
---
services/frontend/components/dashboard/stats-charts.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/services/frontend/components/dashboard/stats-charts.tsx b/services/frontend/components/dashboard/stats-charts.tsx
index df45dcb1..e0b1e647 100644
--- a/services/frontend/components/dashboard/stats-charts.tsx
+++ b/services/frontend/components/dashboard/stats-charts.tsx
@@ -174,9 +174,9 @@ const BarChartCard = React.forwardRef<
{payload?.map((p, index) => {
const name = p.name;
const value = p.value;
- const category =
- categories.find((c) => c.title.toLowerCase() === name) ??
- name;
+ const category = categories.find(
+ (c) => c.title.toLowerCase() === name,
+ ) ?? { title: name, color: "default" };
return (
Date: Tue, 9 Sep 2025 14:54:36 +0200
Subject: [PATCH 29/45] feat: Implement setup mode for application
initialization
- Added setup mode in the backend to handle application configuration when the config file is missing or the application is restarted.
- Introduced signal handling for graceful shutdown of the server.
- Created a new router for setup mode with endpoints for configuring the application and checking setup status.
- Enhanced frontend to include a setup page for user configuration of backend and database settings.
- Implemented dynamic API URL detection in the frontend to accommodate different environments.
- Added a helper script to restart the frontend after setup completion.
- Updated global styles to include ripple animations for UI components.
---
services/backend/handlers/setup/main.go | 473 ++++++++++++++++++
services/backend/main.go | 63 ++-
services/backend/router/main.go | 57 ++-
services/backend/router/setup.go | 16 +
services/frontend/app/layout.tsx | 37 +-
services/frontend/app/setup/page.tsx | 5 +
services/frontend/components/app-content.tsx | 13 +
.../frontend/components/magicui/ripple.tsx | 58 +++
.../frontend/components/setup/page-client.tsx | 470 +++++++++++++++++
services/frontend/lib/api.ts | 83 +++
services/frontend/lib/config.ts | 132 +++++
services/frontend/lib/setup.tsx | 130 +++++
services/frontend/middleware.ts | 26 +-
services/frontend/package.json | 2 +
services/frontend/pnpm-lock.yaml | 13 +
services/frontend/restart-helper/package.json | 9 +
services/frontend/restart-helper/restart.js | 82 +++
services/frontend/styles/globals.css | 12 +
18 files changed, 1656 insertions(+), 25 deletions(-)
create mode 100644 services/backend/handlers/setup/main.go
create mode 100644 services/backend/router/setup.go
create mode 100644 services/frontend/app/setup/page.tsx
create mode 100644 services/frontend/components/app-content.tsx
create mode 100644 services/frontend/components/magicui/ripple.tsx
create mode 100644 services/frontend/components/setup/page-client.tsx
create mode 100644 services/frontend/lib/api.ts
create mode 100644 services/frontend/lib/config.ts
create mode 100644 services/frontend/lib/setup.tsx
create mode 100644 services/frontend/restart-helper/package.json
create mode 100644 services/frontend/restart-helper/restart.js
diff --git a/services/backend/handlers/setup/main.go b/services/backend/handlers/setup/main.go
new file mode 100644
index 00000000..0017c25d
--- /dev/null
+++ b/services/backend/handlers/setup/main.go
@@ -0,0 +1,473 @@
+package setup
+
+import (
+ "crypto/rand"
+ "database/sql"
+ "encoding/base64"
+ "fmt"
+ "net/http"
+ "net/url"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "syscall"
+ "time"
+
+ "github.com/gin-gonic/gin"
+ _ "github.com/lib/pq" // PostgreSQL driver
+ log "github.com/sirupsen/logrus"
+ "gopkg.in/yaml.v3"
+)
+
+type SetupRequest struct {
+ BackendURL string `json:"backend_url" binding:"required"`
+ BackendPort int `json:"backend_port" binding:"required"`
+ Database DatabaseSetup `json:"database" binding:"required"`
+ FrontendURL string `json:"frontend_url" binding:"required"`
+}
+
+type DatabaseSetup struct {
+ Server string `json:"server" binding:"required"`
+ Port int `json:"port" binding:"required"`
+ Name string `json:"name" binding:"required"`
+ User string `json:"user" binding:"required"`
+ Password string `json:"password" binding:"required"`
+}
+
+type BackendConfig struct {
+ LogLevel string `yaml:"log_level"`
+ Port int `yaml:"port"`
+ Database DatabaseConfig `yaml:"database"`
+ JWT JWTConfig `yaml:"jwt"`
+ Encryption EncryptionConfig `yaml:"encryption"`
+ Runner RunnerConfig `yaml:"runner"`
+}
+
+type DatabaseConfig struct {
+ Server string `yaml:"server"`
+ Port int `yaml:"port"`
+ Name string `yaml:"name"`
+ User string `yaml:"user"`
+ Password string `yaml:"password"`
+}
+
+type JWTConfig struct {
+ Secret string `yaml:"secret"`
+}
+
+type EncryptionConfig struct {
+ MasterSecret string `yaml:"master_secret"`
+ Key string `yaml:"key"`
+}
+
+type RunnerConfig struct {
+ SharedRunnerSecret string `yaml:"shared_runner_secret"`
+}
+
+// generateRandomString generates a cryptographically secure random string of specified length
+func generateRandomString(length int) (string, error) {
+ bytes := make([]byte, length)
+ _, err := rand.Read(bytes)
+ if err != nil {
+ return "", err
+ }
+ return base64.URLEncoding.EncodeToString(bytes)[:length], nil
+}
+
+// DatabaseValidationResult contains detailed database validation information
+type DatabaseValidationResult struct {
+ Connected bool `json:"connected"`
+ TablesExist bool `json:"tables_exist"`
+ TableCount int `json:"table_count"`
+ ExistingTables []string `json:"existing_tables,omitempty"`
+ IsEmpty bool `json:"is_empty"`
+ Error string `json:"error,omitempty"`
+ Warning string `json:"warning,omitempty"`
+}
+
+// validateDatabaseConnection tests the database connection and checks table status
+func validateDatabaseConnection(server string, port int, name, user, password string) (*DatabaseValidationResult, error) {
+ result := &DatabaseValidationResult{
+ Connected: false,
+ TablesExist: false,
+ TableCount: 0,
+ ExistingTables: []string{},
+ IsEmpty: true,
+ }
+
+ // Construct PostgreSQL connection string
+ connStr := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
+ server, port, user, password, name)
+
+ // Open connection
+ db, err := sql.Open("postgres", connStr)
+ if err != nil {
+ result.Error = fmt.Sprintf("failed to create database connection: %v", err)
+ return result, fmt.Errorf("failed to create database connection: %v", err)
+ }
+ defer db.Close()
+
+ // Set connection timeout
+ db.SetConnMaxLifetime(5 * time.Second)
+
+ // Test the connection
+ err = db.Ping()
+ if err != nil {
+ result.Error = fmt.Sprintf("failed to connect to database: %v", err)
+ return result, fmt.Errorf("failed to connect to database: %v", err)
+ }
+
+ result.Connected = true
+
+ // Check for existing tables
+ query := `
+ SELECT table_name
+ FROM information_schema.tables
+ WHERE table_schema = 'public'
+ AND table_type = 'BASE TABLE'
+ ORDER BY table_name
+ `
+
+ rows, err := db.Query(query)
+ if err != nil {
+ result.Warning = fmt.Sprintf("could not check tables: %v", err)
+ return result, nil // Connection works, but can't check tables
+ }
+ defer rows.Close()
+
+ var tables []string
+ for rows.Next() {
+ var tableName string
+ if err := rows.Scan(&tableName); err != nil {
+ continue
+ }
+ tables = append(tables, tableName)
+ }
+
+ result.ExistingTables = tables
+ result.TableCount = len(tables)
+ result.TablesExist = len(tables) > 0
+ result.IsEmpty = len(tables) == 0
+
+ // Check if database is empty - if not, return an error
+ if result.IsEmpty {
+ result.Warning = "Database is empty - perfect for a fresh ExFlow installation"
+ return result, nil
+ } else {
+ // Database contains tables - this is an error for setup
+ result.Error = fmt.Sprintf("Database contains %d existing tables: %s. ExFlow setup requires an empty database.",
+ len(tables), strings.Join(tables, ", "))
+ return result, fmt.Errorf("database must be empty for setup - found %d existing tables", len(tables))
+ }
+}
+
+// validateBackendURL tests if the backend URL is accessible and properly formatted
+func validateBackendURL(backendURL string) error {
+ // Parse the URL
+ parsedURL, err := url.Parse(backendURL)
+ if err != nil {
+ return fmt.Errorf("invalid URL format: %v", err)
+ }
+
+ // Check if scheme is provided
+ if parsedURL.Scheme == "" {
+ return fmt.Errorf("URL must include scheme (http:// or https://)")
+ }
+
+ // Check if host is provided
+ if parsedURL.Host == "" {
+ return fmt.Errorf("URL must include host")
+ }
+
+ // For localhost URLs, we can't test connectivity from the backend to itself
+ // since we're in setup mode, so just validate format
+ if strings.Contains(parsedURL.Host, "localhost") || strings.Contains(parsedURL.Host, "127.0.0.1") {
+ return nil
+ }
+
+ // For external URLs, test connectivity
+ client := &http.Client{
+ Timeout: 5 * time.Second,
+ }
+
+ resp, err := client.Get(backendURL + "/api/v1/health")
+ if err != nil {
+ // If health endpoint fails, just warn but don't fail setup
+ log.Warn("Could not verify backend URL accessibility: ", err)
+ return nil
+ }
+ defer resp.Body.Close()
+
+ return nil
+}
+
+// SetupSystem handles the initial system setup
+func SetupSystem(c *gin.Context) {
+ var req SetupRequest
+ if err := c.ShouldBindJSON(&req); err != nil {
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+ return
+ }
+
+ // Validate database connection
+ log.Info("Validating database connection...")
+ dbResult, err := validateDatabaseConnection(req.Database.Server, req.Database.Port, req.Database.Name, req.Database.User, req.Database.Password)
+ if err != nil {
+ log.Error("Database validation failed: ", err)
+ c.JSON(http.StatusBadRequest, gin.H{
+ "error": fmt.Sprintf("Database connection failed: %v", err),
+ "field": "database",
+ "details": dbResult,
+ })
+ return
+ }
+
+ if dbResult.Warning != "" {
+ log.Warn("Database validation warning: ", dbResult.Warning)
+ }
+
+ log.Info("Database connection validated successfully")
+
+ // Validate backend URL format
+ log.Info("Validating backend URL...")
+ if err := validateBackendURL(req.BackendURL); err != nil {
+ log.Error("Backend URL validation failed: ", err)
+ c.JSON(http.StatusBadRequest, gin.H{
+ "error": fmt.Sprintf("Backend URL validation failed: %v", err),
+ "field": "backend_url",
+ })
+ return
+ }
+ log.Info("Backend URL validated successfully")
+
+ // Generate secure secrets
+ jwtSecret, err := generateRandomString(64)
+ if err != nil {
+ log.Error("Failed to generate JWT secret: ", err)
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate JWT secret"})
+ return
+ }
+
+ masterSecret, err := generateRandomString(64)
+ if err != nil {
+ log.Error("Failed to generate master secret: ", err)
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate master secret"})
+ return
+ }
+
+ encryptionKey, err := generateRandomString(32)
+ if err != nil {
+ log.Error("Failed to generate encryption key: ", err)
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate encryption key"})
+ return
+ }
+
+ runnerSecret, err := generateRandomString(32)
+ if err != nil {
+ log.Error("Failed to generate runner secret: ", err)
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate runner secret"})
+ return
+ }
+
+ // Create backend config
+ backendConfig := BackendConfig{
+ LogLevel: "info",
+ Port: req.BackendPort,
+ Database: DatabaseConfig{
+ Server: req.Database.Server,
+ Port: req.Database.Port,
+ Name: req.Database.Name,
+ User: req.Database.User,
+ Password: req.Database.Password,
+ },
+ JWT: JWTConfig{
+ Secret: jwtSecret,
+ },
+ Encryption: EncryptionConfig{
+ MasterSecret: masterSecret,
+ Key: encryptionKey,
+ },
+ Runner: RunnerConfig{
+ SharedRunnerSecret: runnerSecret,
+ },
+ }
+
+ // Write backend config.yaml
+ backendConfigPath := filepath.Join(".", "config.yaml")
+ configData, err := yaml.Marshal(&backendConfig)
+ if err != nil {
+ log.Error("Failed to marshal backend config: ", err)
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create backend config"})
+ return
+ }
+
+ err = os.WriteFile(backendConfigPath, configData, 0600)
+ if err != nil {
+ log.Error("Failed to write backend config: ", err)
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to write backend config"})
+ return
+ }
+
+ // Create frontend .env file
+ frontendEnvPath := filepath.Join("..", "frontend", ".env")
+ envContent := "NEXT_PUBLIC_API_URL=\"" + req.BackendURL + "\"\n"
+
+ err = os.WriteFile(frontendEnvPath, []byte(envContent), 0644)
+ if err != nil {
+ log.Error("Failed to write frontend .env: ", err)
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to write frontend config"})
+ return
+ }
+
+ log.Info("System setup completed successfully")
+ c.JSON(http.StatusOK, gin.H{
+ "message": "Setup completed successfully. Application will restart in full mode.",
+ "backend_config_path": backendConfigPath,
+ "frontend_env_path": frontendEnvPath,
+ "restart_required": true,
+ })
+
+ // Restart the application in a goroutine to allow the response to be sent first
+ go func() {
+ log.Info("Restarting application in full mode...")
+ RestartApplication(nil)
+ }()
+}
+
+// CheckSetupStatus checks if the system has been set up
+func CheckSetupStatus(c *gin.Context) {
+ backendConfigExists := false
+ frontendEnvExists := false
+
+ // Check if backend config exists
+ if _, err := os.Stat(filepath.Join(".", "config.yaml")); err == nil {
+ backendConfigExists = true
+ }
+
+ // Check if frontend .env exists
+ if _, err := os.Stat(filepath.Join("..", "frontend", ".env")); err == nil {
+ frontendEnvExists = true
+ }
+
+ isSetup := backendConfigExists && frontendEnvExists
+
+ c.JSON(http.StatusOK, gin.H{
+ "is_setup": isSetup,
+ "backend_config_exists": backendConfigExists,
+ "frontend_env_exists": frontendEnvExists,
+ })
+}
+
+// ValidateSetupData validates setup configuration without saving
+func ValidateSetupData(c *gin.Context) {
+ var req SetupRequest
+ if err := c.ShouldBindJSON(&req); err != nil {
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+ return
+ }
+
+ validationResults := gin.H{
+ "database_valid": false,
+ "backend_url_valid": false,
+ "validation_errors": []string{},
+ "database_details": nil,
+ }
+
+ // Validate database connection
+ dbResult, err := validateDatabaseConnection(req.Database.Server, req.Database.Port, req.Database.Name, req.Database.User, req.Database.Password)
+ if err != nil {
+ validationResults["validation_errors"] = append(validationResults["validation_errors"].([]string), fmt.Sprintf("Database: %v", err))
+ validationResults["database_details"] = dbResult
+ } else {
+ validationResults["database_valid"] = true
+ validationResults["database_details"] = dbResult
+
+ // Add warning as info message if present
+ if dbResult.Warning != "" {
+ validationResults["validation_errors"] = append(validationResults["validation_errors"].([]string), fmt.Sprintf("Database Info: %s", dbResult.Warning))
+ }
+ }
+
+ // Validate backend URL
+ if err := validateBackendURL(req.BackendURL); err != nil {
+ validationResults["validation_errors"] = append(validationResults["validation_errors"].([]string), fmt.Sprintf("Backend URL: %v", err))
+ } else {
+ validationResults["backend_url_valid"] = true
+ }
+
+ allValid := validationResults["database_valid"].(bool) && validationResults["backend_url_valid"].(bool)
+ validationResults["all_valid"] = allValid
+
+ if allValid {
+ c.JSON(http.StatusOK, validationResults)
+ } else {
+ c.JSON(http.StatusBadRequest, validationResults)
+ }
+}
+
+// RestartApplication restarts the current application process
+func RestartApplication(c *gin.Context) {
+ if c != nil {
+ c.JSON(http.StatusOK, gin.H{"message": "Application restarting..."})
+ }
+
+ log.Info("Restarting application...")
+
+ // Get the current executable path
+ executable, err := os.Executable()
+ if err != nil {
+ log.Error("Failed to get executable path: ", err)
+ if c != nil {
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to restart application"})
+ }
+ return
+ }
+
+ // Get current process arguments
+ args := os.Args[1:] // Exclude the program name
+
+ // Create a new process
+ cmd := exec.Command(executable, args...)
+
+ // Set up environment for the new process
+ cmd.Env = os.Environ()
+ cmd.Env = append(cmd.Env, "EXFLOW_RESTARTED=1") // Flag to indicate this is a restarted process
+
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ cmd.Stdin = os.Stdin
+
+ // For development (go run), we need to stay in the same process group
+ // so that Ctrl+C signals are properly forwarded
+ // For production (compiled binary), we can use process groups
+ isGoRun := strings.Contains(executable, "go-build") || strings.Contains(executable, "/tmp/")
+
+ if !isGoRun {
+ // Production mode - use separate process group for better isolation
+ cmd.SysProcAttr = &syscall.SysProcAttr{
+ Setpgid: true,
+ Pgid: 0,
+ }
+ log.Info("Starting in production mode with separate process group")
+ } else {
+ // Development mode - inherit parent process group for signal forwarding
+ log.Info("Starting in development mode (go run) - inheriting process group")
+ }
+
+ // Start the new process
+ err = cmd.Start()
+ if err != nil {
+ log.Error("Failed to start new process: ", err)
+ if c != nil {
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to restart application"})
+ }
+ return
+ }
+
+ log.Info("New process started with PID: ", cmd.Process.Pid)
+ log.Info("Setup-initiated restart complete")
+
+ // Terminate the current process gracefully
+ os.Exit(0)
+}
diff --git a/services/backend/main.go b/services/backend/main.go
index 3e7a0909..b9971df4 100644
--- a/services/backend/main.go
+++ b/services/backend/main.go
@@ -1,7 +1,12 @@
package main
import (
+ "context"
+ "os"
+ "os/signal"
"strings"
+ "syscall"
+ "time"
"github.com/v1Flows/exFlow/services/backend/config"
"github.com/v1Flows/exFlow/services/backend/database"
@@ -43,10 +48,24 @@ func main() {
log.Info("Starting exFlow API. Version: ", version)
+ // Check if this is a restarted process
+ if os.Getenv("EXFLOW_RESTARTED") == "1" {
+ log.Info("Application restarted after setup completion")
+ }
+
+ // Check if config file exists
+ if _, err := os.Stat(*configFile); os.IsNotExist(err) {
+ log.Info("Config file not found, starting in setup mode")
+ startSetupMode()
+ return
+ }
+
log.Info("Loading Config File: ", *configFile)
err := config.GetInstance().LoadConfig(*configFile)
if err != nil {
- panic(err)
+ log.Error("Failed to load config file, starting in setup mode: ", err)
+ startSetupMode()
+ return
}
cfg := config.Config
@@ -65,5 +84,45 @@ func main() {
}
go background_checks.Init(db)
- router.StartRouter(db, cfg.Port)
+
+ // Set up signal handling for graceful shutdown
+ server := router.StartRouter(db, cfg.Port)
+
+ // Wait for interrupt signal to gracefully shutdown the server
+ quit := make(chan os.Signal, 1)
+ signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
+ <-quit
+ log.Info("Shutting down server...")
+
+ // The server has 30 seconds to finish the request it is currently handling
+ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+ defer cancel()
+ if err := server.Shutdown(ctx); err != nil {
+ log.Fatal("Server forced to shutdown:", err)
+ }
+
+ log.Info("Server exited")
+}
+
+func startSetupMode() {
+ log.Info("Starting in setup mode - limited functionality available")
+ logging("info") // Default to info level logging in setup mode
+
+ // Start router in setup mode (without database connection)
+ server := router.StartSetupRouter(8081) // Default port for setup
+
+ // Wait for interrupt signal to gracefully shutdown the server
+ quit := make(chan os.Signal, 1)
+ signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
+ <-quit
+ log.Info("Shutting down setup server...")
+
+ // The server has 30 seconds to finish the request it is currently handling
+ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+ defer cancel()
+ if err := server.Shutdown(ctx); err != nil {
+ log.Fatal("Setup server forced to shutdown:", err)
+ }
+
+ log.Info("Setup server exited")
}
diff --git a/services/backend/router/main.go b/services/backend/router/main.go
index c2311c67..c4d83fb4 100644
--- a/services/backend/router/main.go
+++ b/services/backend/router/main.go
@@ -1,6 +1,7 @@
package router
import (
+ "net/http"
"strconv"
"time"
@@ -11,12 +12,12 @@ import (
log "github.com/sirupsen/logrus"
)
-func StartRouter(db *bun.DB, port int) {
+func StartRouter(db *bun.DB, port int) *http.Server {
gin.SetMode(gin.ReleaseMode)
router := gin.Default()
router.Use(cors.New(cors.Config{
- AllowOrigins: []string{"https://exflow.org", "http://localhost:3000"},
+ AllowOrigins: []string{"https://exflow.org", "http://localhost:3000", "http://localhost:4000"},
AllowMethods: []string{"GET", "HEAD", "POST", "PUT", "OPTIONS", "DELETE"},
AllowHeaders: []string{"Origin", "Authorization", "X-Requested-With", "Content-Type"},
ExposeHeaders: []string{"Content-Length"},
@@ -38,8 +39,56 @@ func StartRouter(db *bun.DB, port int) {
Token(v1, db)
User(v1, db)
Health(v1)
+ Setup(v1)
}
- log.Info("Starting Router on port ", strconv.Itoa(port))
- router.Run(":" + strconv.Itoa(port))
+ server := &http.Server{
+ Addr: ":" + strconv.Itoa(port),
+ Handler: router,
+ }
+
+ go func() {
+ log.Info("Starting Router on port ", strconv.Itoa(port))
+ if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
+ log.Fatalf("Failed to start server: %v\n", err)
+ }
+ }()
+
+ return server
+}
+
+// StartSetupRouter starts a minimal router for setup mode (no database required)
+func StartSetupRouter(port int) *http.Server {
+ gin.SetMode(gin.ReleaseMode)
+ router := gin.Default()
+
+ router.Use(cors.New(cors.Config{
+ AllowOrigins: []string{"https://exflow.org", "http://localhost:3000", "http://localhost:4000"},
+ AllowMethods: []string{"GET", "HEAD", "POST", "PUT", "OPTIONS", "DELETE"},
+ AllowHeaders: []string{"Origin", "Authorization", "X-Requested-With", "Content-Type"},
+ ExposeHeaders: []string{"Content-Length"},
+ AllowCredentials: true,
+ MaxAge: 12 * time.Hour,
+ }))
+
+ v1 := router.Group("/api/v1")
+ {
+ // Only enable setup and health endpoints in setup mode
+ Health(v1)
+ Setup(v1)
+ }
+
+ server := &http.Server{
+ Addr: ":" + strconv.Itoa(port),
+ Handler: router,
+ }
+
+ go func() {
+ log.Info("Starting Setup Router on port ", strconv.Itoa(port))
+ if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
+ log.Fatalf("Failed to start setup server: %v\n", err)
+ }
+ }()
+
+ return server
}
diff --git a/services/backend/router/setup.go b/services/backend/router/setup.go
new file mode 100644
index 00000000..03c31fac
--- /dev/null
+++ b/services/backend/router/setup.go
@@ -0,0 +1,16 @@
+package router
+
+import (
+ "github.com/gin-gonic/gin"
+ "github.com/v1Flows/exFlow/services/backend/handlers/setup"
+)
+
+func Setup(rg *gin.RouterGroup) {
+ setupGroup := rg.Group("/setup")
+ {
+ setupGroup.POST("/configure", setup.SetupSystem)
+ setupGroup.GET("/status", setup.CheckSetupStatus)
+ setupGroup.POST("/validate", setup.ValidateSetupData)
+ setupGroup.POST("/restart", setup.RestartApplication)
+ }
+}
diff --git a/services/frontend/app/layout.tsx b/services/frontend/app/layout.tsx
index 914093ea..9313c184 100644
--- a/services/frontend/app/layout.tsx
+++ b/services/frontend/app/layout.tsx
@@ -2,11 +2,12 @@ import "@/styles/globals.css";
import { Metadata, Viewport } from "next";
import clsx from "clsx";
import { ReactNode } from "react";
-import { cookies } from "next/headers";
+import { cookies, headers } from "next/headers";
import { siteConfig } from "@/config/site";
import { fontSans } from "@/config/fonts";
import { Navbar } from "@/components/navbar";
+import { AppContent } from "@/components/app-content";
import GetUserDetails from "@/lib/fetch/user/getDetails";
import Footer from "@/components/footer/footer";
import PageGetSettings from "@/lib/fetch/page/settings";
@@ -75,6 +76,10 @@ export default async function RootLayout({
const cookieStore = await cookies();
const sessionCookie = cookieStore.get("session");
+ // get the current page the user is on
+ const headersList = await headers();
+ const currentPage = headersList.get("x-pathname") || "/";
+
const userDetailsData = GetUserDetails();
const settingsData = PageGetSettings();
const flowsData = GetFlows();
@@ -104,20 +109,22 @@ export default async function RootLayout({
)}
>
-
- {sessionCookie && (
-
- )}
- {children}
-
-
+
+
+ {sessionCookie && currentPage !== "/setup" && (
+
+ )}
+ {children}
+
+
+