mirror of
https://github.com/formbricks/formbricks.git
synced 2026-05-13 11:29:31 -05:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a4469dbb46 | |||
| 6dd2e707fe | |||
| 58d5de7d45 | |||
| 7c3fa8b5ea | |||
| 2601169877 | |||
| aecf85815a | |||
| c6ebaea989 | |||
| 68c1422733 | |||
| 6942502baf | |||
| a4bd217761 | |||
| fee770358c | |||
| 44f8f80cac | |||
| 207d044707 | |||
| 858a7f7aa9 | |||
| ac40b90e81 | |||
| aa21b4e442 |
@@ -1,50 +0,0 @@
|
||||
# Fix Summary: Custom Script Error Handling (FORMBRICKS-P5)
|
||||
|
||||
## Problem
|
||||
User-provided custom scripts injected via `customHeadScripts` were calling deprecated MetaMask internal APIs (`window.ethereum._handleChainChanged`), causing unhandled TypeErrors that:
|
||||
- Were reported to Sentry as production errors
|
||||
- Could potentially break the survey experience for users
|
||||
- Occurred when the survey page loaded with certain browser extensions (MetaMask)
|
||||
|
||||
## Root Cause
|
||||
The `CustomScriptsInjector` component was correctly injecting user-provided scripts, but had no protection against runtime errors that occurred *after* the scripts were executed. The existing try-catch block only caught errors during the injection process itself, not runtime errors from the injected code.
|
||||
|
||||
## Solution
|
||||
Enhanced error handling in the `CustomScriptsInjector` component to wrap all user-provided scripts in defensive error handling:
|
||||
|
||||
### Changes Made
|
||||
1. **Inline Script Wrapping** (lines 64-72):
|
||||
- All inline script content is now wrapped in try-catch blocks
|
||||
- Runtime errors are caught and logged to console with `[Formbricks]` prefix
|
||||
- Errors don't break the survey or propagate to error tracking
|
||||
|
||||
2. **External Script Error Handling** (lines 75-77):
|
||||
- Added `onerror` event handlers to all external scripts loaded via `src` attribute
|
||||
- Loading errors are logged to console but don't break functionality
|
||||
|
||||
3. **Documentation**:
|
||||
- Updated JSDoc to clearly state that user scripts are error-isolated
|
||||
- Added inline comments explaining the defensive programming approach
|
||||
|
||||
## Benefits
|
||||
- ✅ Prevents third-party script errors from breaking surveys
|
||||
- ✅ Reduces noise in error tracking (Sentry)
|
||||
- ✅ Maintains debuggability via console warnings
|
||||
- ✅ No breaking changes to existing functionality
|
||||
- ✅ Works for both inline and external scripts
|
||||
|
||||
## Testing Considerations
|
||||
- User scripts with errors will execute up to the point of failure, then stop gracefully
|
||||
- Error messages are visible in browser console for debugging by self-hosted admins
|
||||
- Survey functionality remains intact even if custom scripts fail completely
|
||||
|
||||
## Example
|
||||
**Before**: User script calling `window.ethereum._handleChainChanged()` would throw an unhandled TypeError
|
||||
|
||||
**After**: The error is caught, logged to console as a warning, and the survey continues to function normally
|
||||
|
||||
## Files Modified
|
||||
- `apps/web/modules/survey/link/components/custom-scripts-injector.tsx`
|
||||
|
||||
## Commit
|
||||
- `fix: wrap custom scripts in try-catch to prevent runtime errors` (Fixes FORMBRICKS-P5)
|
||||
@@ -101,6 +101,9 @@ RUN chown -R nextjs:nextjs ./apps/web/public && chmod -R 755 ./apps/web/public
|
||||
# Create packages/database directory structure with proper ownership for runtime migrations
|
||||
RUN mkdir -p ./packages/database/migrations && chown -R nextjs:nextjs ./packages/database
|
||||
|
||||
COPY --from=installer /app/packages/database/package.json ./packages/database/package.json
|
||||
RUN chown nextjs:nextjs ./packages/database/package.json && chmod 644 ./packages/database/package.json
|
||||
|
||||
COPY --from=installer /app/packages/database/schema.prisma ./packages/database/schema.prisma
|
||||
RUN chown nextjs:nextjs ./packages/database/schema.prisma && chmod 644 ./packages/database/schema.prisma
|
||||
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ export const OrganizationBreadcrumb = ({
|
||||
getOrganizationsForSwitcherAction({ organizationId: currentOrganizationId }).then((result) => {
|
||||
if (result?.data) {
|
||||
// Sort organizations by name
|
||||
const sorted = result.data.toSorted((a, b) => a.name.localeCompare(b.name));
|
||||
const sorted = [...result.data].sort((a, b) => a.name.localeCompare(b.name));
|
||||
setOrganizations(sorted);
|
||||
} else {
|
||||
// Handle server errors or validation errors
|
||||
|
||||
@@ -82,7 +82,7 @@ export const ProjectBreadcrumb = ({
|
||||
getProjectsForSwitcherAction({ organizationId: currentOrganizationId }).then((result) => {
|
||||
if (result?.data) {
|
||||
// Sort projects by name
|
||||
const sorted = result.data.toSorted((a, b) => a.name.localeCompare(b.name));
|
||||
const sorted = [...result.data].sort((a, b) => a.name.localeCompare(b.name));
|
||||
setProjects(sorted);
|
||||
} else {
|
||||
// Handle server errors or validation errors
|
||||
|
||||
+5
-1
@@ -9,6 +9,7 @@ import { Alert, AlertDescription } from "@/modules/ui/components/alert";
|
||||
import { IdBadge } from "@/modules/ui/components/id-badge";
|
||||
import { PageContentWrapper } from "@/modules/ui/components/page-content-wrapper";
|
||||
import { PageHeader } from "@/modules/ui/components/page-header";
|
||||
import packageJson from "@/package.json";
|
||||
import { SettingsCard } from "../../components/SettingsCard";
|
||||
import { DeleteOrganization } from "./components/DeleteOrganization";
|
||||
import { EditOrganizationNameForm } from "./components/EditOrganizationNameForm";
|
||||
@@ -81,7 +82,10 @@ const Page = async (props: { params: Promise<{ environmentId: string }> }) => {
|
||||
</SettingsCard>
|
||||
)}
|
||||
|
||||
<IdBadge id={organization.id} label={t("common.organization_id")} variant="column" />
|
||||
<div className="space-y-2">
|
||||
<IdBadge id={organization.id} label={t("common.organization_id")} variant="column" />
|
||||
<IdBadge id={packageJson.version} label={t("common.formbricks_version")} variant="column" />
|
||||
</div>
|
||||
</PageContentWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
+1
-1
@@ -352,7 +352,7 @@ export const AnonymousLinksTab = ({
|
||||
},
|
||||
{
|
||||
title: t("environments.surveys.share.anonymous_links.custom_start_point"),
|
||||
href: "https://formbricks.com/docs/xm-and-surveys/surveys/link-surveys/start-at-question",
|
||||
href: "https://formbricks.com/docs/xm-and-surveys/surveys/link-surveys/start-at-block",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
+2
-2
@@ -241,7 +241,7 @@ export const ResponseFilter = ({ survey }: ResponseFilterProps) => {
|
||||
<Popover open={isOpen} onOpenChange={handleOpenChange}>
|
||||
<PopoverTrigger asChild>
|
||||
<PopoverTriggerButton isOpen={isOpen}>
|
||||
Filter <b>{activeFilterCount > 0 && `(${activeFilterCount})`}</b>
|
||||
{t("common.filter")} <b>{activeFilterCount > 0 && `(${activeFilterCount})`}</b>
|
||||
</PopoverTriggerButton>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
@@ -329,7 +329,7 @@ export const ResponseFilter = ({ survey }: ResponseFilterProps) => {
|
||||
</div>
|
||||
{i !== filterValue.filter.length - 1 && (
|
||||
<div className="my-4 flex items-center">
|
||||
<p className="mr-4 font-semibold text-slate-800">and</p>
|
||||
<p className="mr-4 font-semibold text-slate-800">{t("common.and")}</p>
|
||||
<hr className="w-full text-slate-600" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
} from "@formbricks/types/integration/slack";
|
||||
import { responses } from "@/app/lib/api/response";
|
||||
import { TSessionAuthentication, withV1ApiWrapper } from "@/app/lib/api/with-api-logging";
|
||||
import { SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, WEBAPP_URL } from "@/lib/constants";
|
||||
import { SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, SLACK_REDIRECT_URI, WEBAPP_URL } from "@/lib/constants";
|
||||
import { hasUserEnvironmentAccess } from "@/lib/environment/auth";
|
||||
import { createOrUpdateIntegration, getIntegrationByType } from "@/lib/integration/service";
|
||||
|
||||
@@ -56,6 +56,7 @@ export const GET = withV1ApiWrapper({
|
||||
code,
|
||||
client_id: SLACK_CLIENT_ID,
|
||||
client_secret: SLACK_CLIENT_SECRET,
|
||||
redirect_uri: SLACK_REDIRECT_URI,
|
||||
};
|
||||
const formBody: string[] = [];
|
||||
for (const property in formData) {
|
||||
|
||||
+7
-2
@@ -164,6 +164,7 @@ checksums:
|
||||
common/days: c95fe8aedde21a0b5653dbd0b3c58b48
|
||||
common/default: d9c6dc5c412fe94143dfd1d332ec81d4
|
||||
common/delete: 8bcf303dd10a645b5baacb02b47d72c9
|
||||
common/delete_what: 718ddfcc1dec7f3e8b67856fba838267
|
||||
common/description: e17686a22ffad04cc7bb70524ed4478b
|
||||
common/dev_env: e650911d5e19ba256358e0cda154c005
|
||||
common/development: 85211dbb918bda7a6e87649dcfc1b17a
|
||||
@@ -198,7 +199,9 @@ checksums:
|
||||
common/failed_to_copy_to_clipboard: de836a7d628d36c832809252f188f784
|
||||
common/failed_to_load_organizations: 512808a2b674c7c28bca73f8f91fd87e
|
||||
common/failed_to_load_workspaces: 6ee3448097394517dc605074cd4e6ea4
|
||||
common/filter: 626325a05e4c8800f7ede7012b0cadaf
|
||||
common/finish: ffa7a10f71182b48fefed7135bee24fa
|
||||
common/first_name: cf040a5d6a9fd696be400380cc99f54b
|
||||
common/follow_these: 3a730b242bb17a3f95e01bf0dae86885
|
||||
common/formbricks_version: d9967c797f3e49ca0cae78bc0ebd19cb
|
||||
common/full_name: f45991923345e8322c9ff8cd6b7e2b16
|
||||
@@ -211,6 +214,7 @@ checksums:
|
||||
common/hidden_field: 3ed5c58d0ed359e558cdf7bd33606d2d
|
||||
common/hidden_fields: 3de6cfd308293a826cb8679fd1d49972
|
||||
common/hide_column: 23ce94db148f2d8e4a0923defead6cf1
|
||||
common/id: c8886d38aeea2ed5f785aba4fc96784b
|
||||
common/image: 048ba7a239de0fbd883ade8558415830
|
||||
common/images: 9305827c28694866f49db42b4c51831f
|
||||
common/import: 348b8ab981de5b7f1fca6d7302263bbd
|
||||
@@ -228,6 +232,7 @@ checksums:
|
||||
common/key: 3d1065ab98a1c2f1210507fd5c7bf515
|
||||
common/label: a5c71bf158481233f8215dbd38cc196b
|
||||
common/language: 277fd1a41cc237a437cd1d5e4a80463b
|
||||
common/last_name: 2c9a7de7738ca007ba9023c385149c26
|
||||
common/learn_more: e598091d132f890c37a6d4ed94f6d794
|
||||
common/license_expired: 7af13535e320e4197989472c01387d2c
|
||||
common/light_overlay: 0499907ea7b8405f4267b117998b5a78
|
||||
@@ -1016,7 +1021,7 @@ checksums:
|
||||
environments/settings/general/email_customization_preview_email_heading: 8b798cb8438b3dd356c02dab33b4c897
|
||||
environments/settings/general/email_customization_preview_email_text: fa6ae92403cc8f3c35c03e6c94cbde51
|
||||
environments/settings/general/error_deleting_organization_please_try_again: 7f0fe257d4a0b40bff025408a7766706
|
||||
environments/settings/general/from_your_organization: 4b7970431edb3d0f13c394dbd755a055
|
||||
environments/settings/general/from_your_organization: 9ebd6dcd79f7bfad3fea46ed2e3133d2
|
||||
environments/settings/general/invitation_sent_once_more: e6e5ea066810f9dcb65788aa4f05d6e2
|
||||
environments/settings/general/invite_deleted_successfully: 1c7dca6d0f6870d945288e38cfd2f943
|
||||
environments/settings/general/invite_expires_on: 6fd2356ad91a5f189070c43855904bb4
|
||||
@@ -1369,7 +1374,6 @@ checksums:
|
||||
environments/surveys/edit/follow_ups_modal_updated_successfull_toast: 61204fada3231f4f1fe3866e87e1130a
|
||||
environments/surveys/edit/follow_ups_new: 224c779d252b3e75086e4ed456ba2548
|
||||
environments/surveys/edit/follow_ups_upgrade_button_text: 4cd167527fc6cdb5b0bfc9b486b142a8
|
||||
environments/surveys/edit/form_styling: 1278a2db4257b5500474161133acc857
|
||||
environments/surveys/edit/formbricks_sdk_is_not_connected: 35165b0cac182a98408007a378cc677e
|
||||
environments/surveys/edit/four_points: b289628a6b8a6cd0f7d17a14ca6cd7bf
|
||||
environments/surveys/edit/heading: 79e9dfa461f38a239d34b9833ca103f1
|
||||
@@ -1586,6 +1590,7 @@ checksums:
|
||||
environments/surveys/edit/survey_completed_subheading: db537c356c3ab6564d24de0d11a0fee2
|
||||
environments/surveys/edit/survey_display_settings: 8ed19e6a8e1376f7a1ba037d82c4ae11
|
||||
environments/surveys/edit/survey_placement: 083c10f257337f9648bf9d435b18ec2c
|
||||
environments/surveys/edit/survey_styling: 7f96d6563e934e65687b74374a33b1dc
|
||||
environments/surveys/edit/survey_trigger: f0c7014a684ca566698b87074fad5579
|
||||
environments/surveys/edit/switch_multi_language_on_to_get_started: cca0ef91ee49095da30cd1e3f26c406f
|
||||
environments/surveys/edit/target_block_not_found: 0a0c401017ab32364fec2fcbf815d832
|
||||
|
||||
@@ -63,7 +63,8 @@ export const INVITE_DISABLED = env.INVITE_DISABLED === "1";
|
||||
|
||||
export const SLACK_CLIENT_SECRET = env.SLACK_CLIENT_SECRET;
|
||||
export const SLACK_CLIENT_ID = env.SLACK_CLIENT_ID;
|
||||
export const SLACK_AUTH_URL = `https://slack.com/oauth/v2/authorize?client_id=${env.SLACK_CLIENT_ID}&scope=channels:read,chat:write,chat:write.public,chat:write.customize,groups:read`;
|
||||
export const SLACK_REDIRECT_URI = `${WEBAPP_URL}/api/v1/integrations/slack/callback`;
|
||||
export const SLACK_AUTH_URL = `https://slack.com/oauth/v2/authorize?client_id=${env.SLACK_CLIENT_ID}&scope=channels:read,chat:write,chat:write.public,chat:write.customize,groups:read&redirect_uri=${SLACK_REDIRECT_URI}`;
|
||||
|
||||
export const GOOGLE_SHEETS_CLIENT_ID = env.GOOGLE_SHEETS_CLIENT_ID;
|
||||
export const GOOGLE_SHEETS_CLIENT_SECRET = env.GOOGLE_SHEETS_CLIENT_SECRET;
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"days": "Tage",
|
||||
"default": "Standard",
|
||||
"delete": "Löschen",
|
||||
"delete_what": "{deleteWhat} löschen",
|
||||
"description": "Beschreibung",
|
||||
"dev_env": "Entwicklungsumgebung",
|
||||
"development": "Entwicklung",
|
||||
@@ -225,7 +226,9 @@
|
||||
"failed_to_copy_to_clipboard": "Fehler beim Kopieren in die Zwischenablage",
|
||||
"failed_to_load_organizations": "Fehler beim Laden der Organisationen",
|
||||
"failed_to_load_workspaces": "Projekte konnten nicht geladen werden",
|
||||
"filter": "Filter",
|
||||
"finish": "Fertigstellen",
|
||||
"first_name": "Vorname",
|
||||
"follow_these": "Folge diesen",
|
||||
"formbricks_version": "Formbricks Version",
|
||||
"full_name": "Name",
|
||||
@@ -238,6 +241,7 @@
|
||||
"hidden_field": "Verstecktes Feld",
|
||||
"hidden_fields": "Versteckte Felder",
|
||||
"hide_column": "Spalte ausblenden",
|
||||
"id": "ID",
|
||||
"image": "Bild",
|
||||
"images": "Bilder",
|
||||
"import": "Importieren",
|
||||
@@ -255,6 +259,7 @@
|
||||
"key": "Schlüssel",
|
||||
"label": "Bezeichnung",
|
||||
"language": "Sprache",
|
||||
"last_name": "Nachname",
|
||||
"learn_more": "Mehr erfahren",
|
||||
"license_expired": "License Expired",
|
||||
"light_overlay": "Helle Überlagerung",
|
||||
@@ -1077,7 +1082,7 @@
|
||||
"email_customization_preview_email_heading": "Hey {userName}",
|
||||
"email_customization_preview_email_text": "Dies ist eine E-Mail-Vorschau, um dir zu zeigen, welches Logo in den E-Mails gerendert wird.",
|
||||
"error_deleting_organization_please_try_again": "Fehler beim Löschen der Organisation. Bitte versuche es erneut.",
|
||||
"from_your_organization": "von deiner Organisation",
|
||||
"from_your_organization": "{memberName} aus Ihrer Organisation",
|
||||
"invitation_sent_once_more": "Einladung nochmal gesendet.",
|
||||
"invite_deleted_successfully": "Einladung erfolgreich gelöscht",
|
||||
"invite_expires_on": "Einladung läuft ab am {date}",
|
||||
@@ -1440,7 +1445,6 @@
|
||||
"follow_ups_modal_updated_successfull_toast": "Nachverfolgung aktualisiert und wird gespeichert, sobald du die Umfrage speicherst.",
|
||||
"follow_ups_new": "Neues Follow-up",
|
||||
"follow_ups_upgrade_button_text": "Upgrade, um Follow-ups zu aktivieren",
|
||||
"form_styling": "Umfrage Styling",
|
||||
"formbricks_sdk_is_not_connected": "Formbricks SDK ist nicht verbunden",
|
||||
"four_points": "4 Punkte",
|
||||
"heading": "Überschrift",
|
||||
@@ -1659,6 +1663,7 @@
|
||||
"survey_completed_subheading": "Diese kostenlose und quelloffene Umfrage wurde geschlossen",
|
||||
"survey_display_settings": "Einstellungen zur Anzeige der Umfrage",
|
||||
"survey_placement": "Platzierung der Umfrage",
|
||||
"survey_styling": "Umfrage Styling",
|
||||
"survey_trigger": "Auslöser der Umfrage",
|
||||
"switch_multi_language_on_to_get_started": "Aktiviere Mehrsprachigkeit, um loszulegen 👉",
|
||||
"target_block_not_found": "Zielblock nicht gefunden",
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"days": "days",
|
||||
"default": "Default",
|
||||
"delete": "Delete",
|
||||
"delete_what": "Delete {deleteWhat}",
|
||||
"description": "Description",
|
||||
"dev_env": "Dev Environment",
|
||||
"development": "Development",
|
||||
@@ -225,7 +226,9 @@
|
||||
"failed_to_copy_to_clipboard": "Failed to copy to clipboard",
|
||||
"failed_to_load_organizations": "Failed to load organizations",
|
||||
"failed_to_load_workspaces": "Failed to load workspaces",
|
||||
"filter": "Filter",
|
||||
"finish": "Finish",
|
||||
"first_name": "First Name",
|
||||
"follow_these": "Follow these",
|
||||
"formbricks_version": "Formbricks Version",
|
||||
"full_name": "Full name",
|
||||
@@ -238,6 +241,7 @@
|
||||
"hidden_field": "Hidden field",
|
||||
"hidden_fields": "Hidden fields",
|
||||
"hide_column": "Hide column",
|
||||
"id": "ID",
|
||||
"image": "Image",
|
||||
"images": "Images",
|
||||
"import": "Import",
|
||||
@@ -255,6 +259,7 @@
|
||||
"key": "Key",
|
||||
"label": "Label",
|
||||
"language": "Language",
|
||||
"last_name": "Last Name",
|
||||
"learn_more": "Learn more",
|
||||
"license_expired": "License Expired",
|
||||
"light_overlay": "Light overlay",
|
||||
@@ -1077,7 +1082,7 @@
|
||||
"email_customization_preview_email_heading": "Hey {userName}",
|
||||
"email_customization_preview_email_text": "This is an email preview to show you which logo will be rendered in the emails.",
|
||||
"error_deleting_organization_please_try_again": "Error deleting organization. Please try again.",
|
||||
"from_your_organization": "from your organization",
|
||||
"from_your_organization": "{memberName} from your organization",
|
||||
"invitation_sent_once_more": "Invitation sent once more.",
|
||||
"invite_deleted_successfully": "Invite deleted successfully",
|
||||
"invite_expires_on": "Invite expires on {date}",
|
||||
@@ -1440,7 +1445,6 @@
|
||||
"follow_ups_modal_updated_successfull_toast": "Follow-up updated and will be saved once you save the survey.",
|
||||
"follow_ups_new": "New follow-up",
|
||||
"follow_ups_upgrade_button_text": "Upgrade to enable follow-ups",
|
||||
"form_styling": "Form styling",
|
||||
"formbricks_sdk_is_not_connected": "Formbricks SDK is not connected",
|
||||
"four_points": "4 points",
|
||||
"heading": "Heading",
|
||||
@@ -1659,6 +1663,7 @@
|
||||
"survey_completed_subheading": "This free & open-source survey has been closed",
|
||||
"survey_display_settings": "Survey Display Settings",
|
||||
"survey_placement": "Survey Placement",
|
||||
"survey_styling": "Survey styling",
|
||||
"survey_trigger": "Survey Trigger",
|
||||
"switch_multi_language_on_to_get_started": "Switch multi-language on to get started 👉",
|
||||
"target_block_not_found": "Target block not found",
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"days": "días",
|
||||
"default": "Predeterminado",
|
||||
"delete": "Eliminar",
|
||||
"delete_what": "Eliminar {deleteWhat}",
|
||||
"description": "Descripción",
|
||||
"dev_env": "Entorno de desarrollo",
|
||||
"development": "Desarrollo",
|
||||
@@ -225,7 +226,9 @@
|
||||
"failed_to_copy_to_clipboard": "Error al copiar al portapapeles",
|
||||
"failed_to_load_organizations": "Error al cargar organizaciones",
|
||||
"failed_to_load_workspaces": "Error al cargar los proyectos",
|
||||
"filter": "Filtro",
|
||||
"finish": "Finalizar",
|
||||
"first_name": "Nombre",
|
||||
"follow_these": "Sigue estos",
|
||||
"formbricks_version": "Versión de Formbricks",
|
||||
"full_name": "Nombre completo",
|
||||
@@ -238,6 +241,7 @@
|
||||
"hidden_field": "Campo oculto",
|
||||
"hidden_fields": "Campos ocultos",
|
||||
"hide_column": "Ocultar columna",
|
||||
"id": "ID",
|
||||
"image": "Imagen",
|
||||
"images": "Imágenes",
|
||||
"import": "Importar",
|
||||
@@ -255,6 +259,7 @@
|
||||
"key": "Clave",
|
||||
"label": "Etiqueta",
|
||||
"language": "Idioma",
|
||||
"last_name": "Apellido",
|
||||
"learn_more": "Saber más",
|
||||
"license_expired": "License Expired",
|
||||
"light_overlay": "Superposición clara",
|
||||
@@ -1077,7 +1082,7 @@
|
||||
"email_customization_preview_email_heading": "Hola {userName}",
|
||||
"email_customization_preview_email_text": "Este es un correo electrónico de vista previa para mostrarte qué logotipo se mostrará en los correos electrónicos.",
|
||||
"error_deleting_organization_please_try_again": "Error al eliminar la organización. Por favor, inténtalo de nuevo.",
|
||||
"from_your_organization": "de tu organización",
|
||||
"from_your_organization": "{memberName} de tu organización",
|
||||
"invitation_sent_once_more": "Invitación enviada una vez más.",
|
||||
"invite_deleted_successfully": "Invitación eliminada correctamente",
|
||||
"invite_expires_on": "La invitación expira el {date}",
|
||||
@@ -1440,7 +1445,6 @@
|
||||
"follow_ups_modal_updated_successfull_toast": "Seguimiento actualizado y se guardará cuando guardes la encuesta.",
|
||||
"follow_ups_new": "Nuevo seguimiento",
|
||||
"follow_ups_upgrade_button_text": "Actualiza para habilitar seguimientos",
|
||||
"form_styling": "Estilo del formulario",
|
||||
"formbricks_sdk_is_not_connected": "El SDK de Formbricks no está conectado",
|
||||
"four_points": "4 puntos",
|
||||
"heading": "Encabezado",
|
||||
@@ -1659,6 +1663,7 @@
|
||||
"survey_completed_subheading": "Esta encuesta gratuita y de código abierto ha sido cerrada",
|
||||
"survey_display_settings": "Ajustes de visualización de la encuesta",
|
||||
"survey_placement": "Ubicación de la encuesta",
|
||||
"survey_styling": "Estilo del formulario",
|
||||
"survey_trigger": "Activador de la encuesta",
|
||||
"switch_multi_language_on_to_get_started": "Activa el modo multiidioma para comenzar 👉",
|
||||
"target_block_not_found": "Bloque objetivo no encontrado",
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"days": "jours",
|
||||
"default": "Par défaut",
|
||||
"delete": "Supprimer",
|
||||
"delete_what": "Supprimer {deleteWhat}",
|
||||
"description": "Description",
|
||||
"dev_env": "Environnement de développement",
|
||||
"development": "Développement",
|
||||
@@ -225,7 +226,9 @@
|
||||
"failed_to_copy_to_clipboard": "Échec de la copie dans le presse-papiers",
|
||||
"failed_to_load_organizations": "Échec du chargement des organisations",
|
||||
"failed_to_load_workspaces": "Échec du chargement des projets",
|
||||
"filter": "Filtre",
|
||||
"finish": "Terminer",
|
||||
"first_name": "Prénom",
|
||||
"follow_these": "Suivez ceci",
|
||||
"formbricks_version": "Version de Formbricks",
|
||||
"full_name": "Nom complet",
|
||||
@@ -238,6 +241,7 @@
|
||||
"hidden_field": "Champ caché",
|
||||
"hidden_fields": "Champs cachés",
|
||||
"hide_column": "Cacher la colonne",
|
||||
"id": "ID",
|
||||
"image": "Image",
|
||||
"images": "Images",
|
||||
"import": "Importer",
|
||||
@@ -255,6 +259,7 @@
|
||||
"key": "Clé",
|
||||
"label": "Étiquette",
|
||||
"language": "Langue",
|
||||
"last_name": "Nom de famille",
|
||||
"learn_more": "En savoir plus",
|
||||
"license_expired": "License Expired",
|
||||
"light_overlay": "Claire",
|
||||
@@ -1077,7 +1082,7 @@
|
||||
"email_customization_preview_email_heading": "Salut {userName}",
|
||||
"email_customization_preview_email_text": "Cette est une prévisualisation d'e-mail pour vous montrer quel logo sera rendu dans les e-mails.",
|
||||
"error_deleting_organization_please_try_again": "Erreur lors de la suppression de l'organisation. Veuillez réessayer.",
|
||||
"from_your_organization": "de votre organisation",
|
||||
"from_your_organization": "{memberName} de votre organisation",
|
||||
"invitation_sent_once_more": "Invitation envoyée une fois de plus.",
|
||||
"invite_deleted_successfully": "Invitation supprimée avec succès",
|
||||
"invite_expires_on": "L'invitation expire le {date}",
|
||||
@@ -1440,7 +1445,6 @@
|
||||
"follow_ups_modal_updated_successfull_toast": "\"Suivi mis à jour et sera enregistré une fois que vous sauvegarderez le sondage.\"",
|
||||
"follow_ups_new": "Nouveau suivi",
|
||||
"follow_ups_upgrade_button_text": "Passez à la version supérieure pour activer les relances",
|
||||
"form_styling": "Style de formulaire",
|
||||
"formbricks_sdk_is_not_connected": "Le SDK Formbricks n'est pas connecté",
|
||||
"four_points": "4 points",
|
||||
"heading": "En-tête",
|
||||
@@ -1659,6 +1663,7 @@
|
||||
"survey_completed_subheading": "Cette enquête gratuite et open-source a été fermée",
|
||||
"survey_display_settings": "Paramètres d'affichage de l'enquête",
|
||||
"survey_placement": "Placement de l'enquête",
|
||||
"survey_styling": "Style de formulaire",
|
||||
"survey_trigger": "Déclencheur d'enquête",
|
||||
"switch_multi_language_on_to_get_started": "Activez le mode multilingue pour commencer 👉",
|
||||
"target_block_not_found": "Bloc cible non trouvé",
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"days": "napok",
|
||||
"default": "Alapértelmezett",
|
||||
"delete": "Törlés",
|
||||
"delete_what": "{deleteWhat} törlése",
|
||||
"description": "Leírás",
|
||||
"dev_env": "Fejlesztői környezet",
|
||||
"development": "Fejlesztés",
|
||||
@@ -225,7 +226,9 @@
|
||||
"failed_to_copy_to_clipboard": "Nem sikerült másolni a vágólapra",
|
||||
"failed_to_load_organizations": "Nem sikerült betölteni a szervezeteket",
|
||||
"failed_to_load_workspaces": "Nem sikerült a munkaterületek betöltése",
|
||||
"filter": "Szűrő",
|
||||
"finish": "Befejezés",
|
||||
"first_name": "Keresztnév",
|
||||
"follow_these": "Ezek követése",
|
||||
"formbricks_version": "Formbricks verziója",
|
||||
"full_name": "Teljes név",
|
||||
@@ -238,6 +241,7 @@
|
||||
"hidden_field": "Rejtett mező",
|
||||
"hidden_fields": "Rejtett mezők",
|
||||
"hide_column": "Oszlop elrejtése",
|
||||
"id": "ID",
|
||||
"image": "Kép",
|
||||
"images": "Képek",
|
||||
"import": "Importálás",
|
||||
@@ -255,6 +259,7 @@
|
||||
"key": "Kulcs",
|
||||
"label": "Címke",
|
||||
"language": "Nyelv",
|
||||
"last_name": "Vezetéknév",
|
||||
"learn_more": "Tudjon meg többet",
|
||||
"license_expired": "A licenc lejárt",
|
||||
"light_overlay": "Világos rávetítés",
|
||||
@@ -1077,7 +1082,7 @@
|
||||
"email_customization_preview_email_heading": "Helló {userName}",
|
||||
"email_customization_preview_email_text": "Ez egy e-mail előnézet, amely azt mutatja meg, hogy melyik logó fog megjelenni az e-mailekben.",
|
||||
"error_deleting_organization_please_try_again": "Hiba a szervezet törlésekor. Próbálja meg újra.",
|
||||
"from_your_organization": "a szervezetétől",
|
||||
"from_your_organization": "{memberName} a szervezetből",
|
||||
"invitation_sent_once_more": "A meghívó még egyszer elküldve.",
|
||||
"invite_deleted_successfully": "A meghívó sikeresen törölve",
|
||||
"invite_expires_on": "A meghívó lejár ekkor: {date}",
|
||||
@@ -1440,7 +1445,6 @@
|
||||
"follow_ups_modal_updated_successfull_toast": "A követés frissítve, és akkor lesz elmentve, ha elmenti a kérdőívet.",
|
||||
"follow_ups_new": "Új követés",
|
||||
"follow_ups_upgrade_button_text": "Magasabb csomagra váltás a követések engedélyezéséhez",
|
||||
"form_styling": "Űrlap stílusának beállítása",
|
||||
"formbricks_sdk_is_not_connected": "A Formbricks SDK nincs csatlakoztatva",
|
||||
"four_points": "4 pont",
|
||||
"heading": "Címsor",
|
||||
@@ -1659,6 +1663,7 @@
|
||||
"survey_completed_subheading": "Ez a szabad és nyílt forráskódú kérdőív le lett zárva",
|
||||
"survey_display_settings": "Kérdőív megjelenítésének beállításai",
|
||||
"survey_placement": "Kérdőív elhelyezése",
|
||||
"survey_styling": "Űrlap stílusának beállítása",
|
||||
"survey_trigger": "Kérdőív aktiválója",
|
||||
"switch_multi_language_on_to_get_started": "Kapcsolja be a többnyelvűséget a kezdéshez 👉",
|
||||
"target_block_not_found": "A célblokk nem található",
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"days": "日",
|
||||
"default": "デフォルト",
|
||||
"delete": "削除",
|
||||
"delete_what": "{deleteWhat}を削除",
|
||||
"description": "説明",
|
||||
"dev_env": "開発環境",
|
||||
"development": "開発",
|
||||
@@ -225,7 +226,9 @@
|
||||
"failed_to_copy_to_clipboard": "クリップボードへのコピーに失敗しました",
|
||||
"failed_to_load_organizations": "組織の読み込みに失敗しました",
|
||||
"failed_to_load_workspaces": "ワークスペースの読み込みに失敗しました",
|
||||
"filter": "フィルター",
|
||||
"finish": "完了",
|
||||
"first_name": "名",
|
||||
"follow_these": "こちらの手順に従って",
|
||||
"formbricks_version": "Formbricksバージョン",
|
||||
"full_name": "氏名",
|
||||
@@ -238,6 +241,7 @@
|
||||
"hidden_field": "非表示フィールド",
|
||||
"hidden_fields": "非表示フィールド",
|
||||
"hide_column": "列を非表示",
|
||||
"id": "ID",
|
||||
"image": "画像",
|
||||
"images": "画像",
|
||||
"import": "インポート",
|
||||
@@ -255,6 +259,7 @@
|
||||
"key": "キー",
|
||||
"label": "ラベル",
|
||||
"language": "言語",
|
||||
"last_name": "姓",
|
||||
"learn_more": "詳細を見る",
|
||||
"license_expired": "License Expired",
|
||||
"light_overlay": "明るいオーバーレイ",
|
||||
@@ -1077,7 +1082,7 @@
|
||||
"email_customization_preview_email_heading": "こんにちは、{userName}さん",
|
||||
"email_customization_preview_email_text": "これは、メールに表示されるロゴを確認するためのプレビューメールです。",
|
||||
"error_deleting_organization_please_try_again": "組織の削除中にエラーが発生しました。もう一度お試しください。",
|
||||
"from_your_organization": "あなたの組織から",
|
||||
"from_your_organization": "組織から{memberName}を削除",
|
||||
"invitation_sent_once_more": "招待状を再度送信しました。",
|
||||
"invite_deleted_successfully": "招待を正常に削除しました",
|
||||
"invite_expires_on": "招待は{date}に期限切れ",
|
||||
@@ -1440,7 +1445,6 @@
|
||||
"follow_ups_modal_updated_successfull_toast": "フォローアップ が 更新され、 アンケートを 保存すると保存されます。",
|
||||
"follow_ups_new": "新しいフォローアップ",
|
||||
"follow_ups_upgrade_button_text": "フォローアップを有効にするためにアップグレード",
|
||||
"form_styling": "フォームのスタイル",
|
||||
"formbricks_sdk_is_not_connected": "Formbricks SDKが接続されていません",
|
||||
"four_points": "4点",
|
||||
"heading": "見出し",
|
||||
@@ -1659,6 +1663,7 @@
|
||||
"survey_completed_subheading": "この無料のオープンソースフォームは閉鎖されました",
|
||||
"survey_display_settings": "フォーム表示設定",
|
||||
"survey_placement": "フォームの配置",
|
||||
"survey_styling": "フォームのスタイル",
|
||||
"survey_trigger": "フォームのトリガー",
|
||||
"switch_multi_language_on_to_get_started": "多言語機能をオンにして開始 👉",
|
||||
"target_block_not_found": "対象ブロックが見つかりません",
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"days": "dagen",
|
||||
"default": "Standaard",
|
||||
"delete": "Verwijderen",
|
||||
"delete_what": "Verwijder {deleteWhat}",
|
||||
"description": "Beschrijving",
|
||||
"dev_env": "Ontwikkelomgeving",
|
||||
"development": "Ontwikkeling",
|
||||
@@ -225,7 +226,9 @@
|
||||
"failed_to_copy_to_clipboard": "Kopiëren naar klembord mislukt",
|
||||
"failed_to_load_organizations": "Laden van organisaties mislukt",
|
||||
"failed_to_load_workspaces": "Laden van werkruimtes mislukt",
|
||||
"filter": "Filter",
|
||||
"finish": "Finish",
|
||||
"first_name": "Voornaam",
|
||||
"follow_these": "Volg deze",
|
||||
"formbricks_version": "Formbricks-versie",
|
||||
"full_name": "Volledige naam",
|
||||
@@ -238,6 +241,7 @@
|
||||
"hidden_field": "Verborgen veld",
|
||||
"hidden_fields": "Verborgen velden",
|
||||
"hide_column": "Kolom verbergen",
|
||||
"id": "ID",
|
||||
"image": "Afbeelding",
|
||||
"images": "Afbeeldingen",
|
||||
"import": "Importeren",
|
||||
@@ -255,6 +259,7 @@
|
||||
"key": "Sleutel",
|
||||
"label": "Label",
|
||||
"language": "Taal",
|
||||
"last_name": "Achternaam",
|
||||
"learn_more": "Meer informatie",
|
||||
"license_expired": "License Expired",
|
||||
"light_overlay": "Lichte overlay",
|
||||
@@ -1077,7 +1082,7 @@
|
||||
"email_customization_preview_email_heading": "Hé {userName}",
|
||||
"email_customization_preview_email_text": "Dit is een e-mailvoorbeeld om u te laten zien welk logo in de e-mails wordt weergegeven.",
|
||||
"error_deleting_organization_please_try_again": "Fout bij verwijderen van organisatie. Probeer het opnieuw.",
|
||||
"from_your_organization": "vanuit uw organisatie",
|
||||
"from_your_organization": "{memberName} uit je organisatie",
|
||||
"invitation_sent_once_more": "Uitnodiging nogmaals verzonden.",
|
||||
"invite_deleted_successfully": "Uitnodiging succesvol verwijderd",
|
||||
"invite_expires_on": "Uitnodiging verloopt op {date}",
|
||||
@@ -1440,7 +1445,6 @@
|
||||
"follow_ups_modal_updated_successfull_toast": "Follow-up bijgewerkt en wordt opgeslagen zodra u de enquête opslaat.",
|
||||
"follow_ups_new": "Nieuw vervolg",
|
||||
"follow_ups_upgrade_button_text": "Upgrade om follow-ups mogelijk te maken",
|
||||
"form_styling": "Vorm styling",
|
||||
"formbricks_sdk_is_not_connected": "Formbricks SDK is niet verbonden",
|
||||
"four_points": "4 punten",
|
||||
"heading": "Rubriek",
|
||||
@@ -1659,6 +1663,7 @@
|
||||
"survey_completed_subheading": "Deze gratis en open source-enquête is gesloten",
|
||||
"survey_display_settings": "Enquêteweergave-instellingen",
|
||||
"survey_placement": "Enquête plaatsing",
|
||||
"survey_styling": "Vorm styling",
|
||||
"survey_trigger": "Enquêtetrigger",
|
||||
"switch_multi_language_on_to_get_started": "Schakel meertaligheid in om te beginnen 👉",
|
||||
"target_block_not_found": "Doelblok niet gevonden",
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"days": "dias",
|
||||
"default": "Padrão",
|
||||
"delete": "Apagar",
|
||||
"delete_what": "Excluir {deleteWhat}",
|
||||
"description": "Descrição",
|
||||
"dev_env": "Ambiente de Desenvolvimento",
|
||||
"development": "Desenvolvimento",
|
||||
@@ -225,7 +226,9 @@
|
||||
"failed_to_copy_to_clipboard": "Falha ao copiar para a área de transferência",
|
||||
"failed_to_load_organizations": "Falha ao carregar organizações",
|
||||
"failed_to_load_workspaces": "Falha ao carregar projetos",
|
||||
"filter": "Filtro",
|
||||
"finish": "Terminar",
|
||||
"first_name": "Primeiro nome",
|
||||
"follow_these": "Siga esses",
|
||||
"formbricks_version": "Versão do Formbricks",
|
||||
"full_name": "Nome completo",
|
||||
@@ -238,6 +241,7 @@
|
||||
"hidden_field": "Campo oculto",
|
||||
"hidden_fields": "Campos ocultos",
|
||||
"hide_column": "Ocultar coluna",
|
||||
"id": "ID",
|
||||
"image": "imagem",
|
||||
"images": "Imagens",
|
||||
"import": "importar",
|
||||
@@ -255,6 +259,7 @@
|
||||
"key": "Chave",
|
||||
"label": "Etiqueta",
|
||||
"language": "Língua",
|
||||
"last_name": "Sobrenome",
|
||||
"learn_more": "Saiba mais",
|
||||
"license_expired": "License Expired",
|
||||
"light_overlay": "sobreposição leve",
|
||||
@@ -1077,7 +1082,7 @@
|
||||
"email_customization_preview_email_heading": "Oi {userName}",
|
||||
"email_customization_preview_email_text": "Esta é uma pré-visualização de e-mail para mostrar qual logo será renderizado nos e-mails.",
|
||||
"error_deleting_organization_please_try_again": "Erro ao deletar a organização. Por favor, tente novamente.",
|
||||
"from_your_organization": "da sua organização",
|
||||
"from_your_organization": "{memberName} da sua organização",
|
||||
"invitation_sent_once_more": "Convite enviado de novo.",
|
||||
"invite_deleted_successfully": "Convite deletado com sucesso",
|
||||
"invite_expires_on": "O convite expira em {date}",
|
||||
@@ -1440,7 +1445,6 @@
|
||||
"follow_ups_modal_updated_successfull_toast": "Acompanhamento atualizado e será salvo assim que você salvar a pesquisa.",
|
||||
"follow_ups_new": "Novo acompanhamento",
|
||||
"follow_ups_upgrade_button_text": "Atualize para habilitar os Acompanhamentos",
|
||||
"form_styling": "Estilização de Formulários",
|
||||
"formbricks_sdk_is_not_connected": "O SDK do Formbricks não está conectado",
|
||||
"four_points": "4 pontos",
|
||||
"heading": "Título",
|
||||
@@ -1659,6 +1663,7 @@
|
||||
"survey_completed_subheading": "Essa pesquisa gratuita e de código aberto foi encerrada",
|
||||
"survey_display_settings": "Configurações de Exibição da Pesquisa",
|
||||
"survey_placement": "Posicionamento da Pesquisa",
|
||||
"survey_styling": "Estilização de Formulários",
|
||||
"survey_trigger": "Gatilho de Pesquisa",
|
||||
"switch_multi_language_on_to_get_started": "Ative o modo multilíngue para começar 👉",
|
||||
"target_block_not_found": "Bloco de destino não encontrado",
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"days": "dias",
|
||||
"default": "Padrão",
|
||||
"delete": "Eliminar",
|
||||
"delete_what": "Eliminar {deleteWhat}",
|
||||
"description": "Descrição",
|
||||
"dev_env": "Ambiente de Desenvolvimento",
|
||||
"development": "Desenvolvimento",
|
||||
@@ -225,7 +226,9 @@
|
||||
"failed_to_copy_to_clipboard": "Falha ao copiar para a área de transferência",
|
||||
"failed_to_load_organizations": "Falha ao carregar organizações",
|
||||
"failed_to_load_workspaces": "Falha ao carregar projetos",
|
||||
"filter": "Filtro",
|
||||
"finish": "Concluir",
|
||||
"first_name": "Primeiro nome",
|
||||
"follow_these": "Siga estes",
|
||||
"formbricks_version": "Versão do Formbricks",
|
||||
"full_name": "Nome completo",
|
||||
@@ -238,6 +241,7 @@
|
||||
"hidden_field": "Campo oculto",
|
||||
"hidden_fields": "Campos ocultos",
|
||||
"hide_column": "Ocultar coluna",
|
||||
"id": "ID",
|
||||
"image": "Imagem",
|
||||
"images": "Imagens",
|
||||
"import": "Importar",
|
||||
@@ -255,6 +259,7 @@
|
||||
"key": "Chave",
|
||||
"label": "Etiqueta",
|
||||
"language": "Idioma",
|
||||
"last_name": "Apelido",
|
||||
"learn_more": "Saiba mais",
|
||||
"license_expired": "License Expired",
|
||||
"light_overlay": "Sobreposição leve",
|
||||
@@ -1077,7 +1082,7 @@
|
||||
"email_customization_preview_email_heading": "Olá {userName}",
|
||||
"email_customization_preview_email_text": "Esta é uma pré-visualização de email para mostrar qual logotipo será exibido nos emails.",
|
||||
"error_deleting_organization_please_try_again": "Erro ao eliminar a organização. Por favor, tente novamente.",
|
||||
"from_your_organization": "da sua organização",
|
||||
"from_your_organization": "{memberName} da sua organização",
|
||||
"invitation_sent_once_more": "Convite enviado mais uma vez.",
|
||||
"invite_deleted_successfully": "Convite eliminado com sucesso",
|
||||
"invite_expires_on": "O convite expira em {date}",
|
||||
@@ -1440,7 +1445,6 @@
|
||||
"follow_ups_modal_updated_successfull_toast": "Seguimento atualizado e será guardado assim que guardar o questionário.",
|
||||
"follow_ups_new": "Novo acompanhamento",
|
||||
"follow_ups_upgrade_button_text": "Atualize para ativar os acompanhamentos",
|
||||
"form_styling": "Estilo do formulário",
|
||||
"formbricks_sdk_is_not_connected": "O SDK do Formbricks não está conectado",
|
||||
"four_points": "4 pontos",
|
||||
"heading": "Cabeçalho",
|
||||
@@ -1659,6 +1663,7 @@
|
||||
"survey_completed_subheading": "Este inquérito gratuito e de código aberto foi encerrado",
|
||||
"survey_display_settings": "Configurações de Exibição do Inquérito",
|
||||
"survey_placement": "Colocação do Inquérito",
|
||||
"survey_styling": "Estilo do formulário",
|
||||
"survey_trigger": "Desencadeador de Inquérito",
|
||||
"switch_multi_language_on_to_get_started": "Ative o modo multilingue para começar 👉",
|
||||
"target_block_not_found": "Bloco de destino não encontrado",
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"days": "zile",
|
||||
"default": "Implicit",
|
||||
"delete": "Șterge",
|
||||
"delete_what": "Șterge {deleteWhat}",
|
||||
"description": "Descriere",
|
||||
"dev_env": "Mediu de dezvoltare",
|
||||
"development": "Dezvoltare",
|
||||
@@ -225,7 +226,9 @@
|
||||
"failed_to_copy_to_clipboard": "Nu s-a reușit copierea în clipboard",
|
||||
"failed_to_load_organizations": "Nu s-a reușit încărcarea organizațiilor",
|
||||
"failed_to_load_workspaces": "Nu s-au putut încărca workspaces",
|
||||
"filter": "Filtru",
|
||||
"finish": "Finalizează",
|
||||
"first_name": "Prenume",
|
||||
"follow_these": "Urmați acestea",
|
||||
"formbricks_version": "Versiunea Formbricks",
|
||||
"full_name": "Nume complet",
|
||||
@@ -238,6 +241,7 @@
|
||||
"hidden_field": "Câmp ascuns",
|
||||
"hidden_fields": "Câmpuri ascunse",
|
||||
"hide_column": "Ascunde coloana",
|
||||
"id": "ID",
|
||||
"image": "Imagine",
|
||||
"images": "Imagini",
|
||||
"import": "Import",
|
||||
@@ -255,6 +259,7 @@
|
||||
"key": "Cheie",
|
||||
"label": "Etichetă",
|
||||
"language": "Limba",
|
||||
"last_name": "Nume de familie",
|
||||
"learn_more": "Află mai multe",
|
||||
"license_expired": "License Expired",
|
||||
"light_overlay": "Suprapunere ușoară",
|
||||
@@ -1077,7 +1082,7 @@
|
||||
"email_customization_preview_email_heading": "Salut {userName}",
|
||||
"email_customization_preview_email_text": "Acesta este o previzualizare a e-mailului pentru a vă arăta ce logo va fi afișat în e-mailurile.",
|
||||
"error_deleting_organization_please_try_again": "Eroare la ștergerea organizației. Vă rugăm să încercați din nou.",
|
||||
"from_your_organization": "din organizația ta",
|
||||
"from_your_organization": "{memberName} din organizația ta",
|
||||
"invitation_sent_once_more": "Invitație trimisă din nou.",
|
||||
"invite_deleted_successfully": "Invitație ștearsă cu succes",
|
||||
"invite_expires_on": "Invitația expiră pe {date}",
|
||||
@@ -1440,7 +1445,6 @@
|
||||
"follow_ups_modal_updated_successfull_toast": "Urmărirea a fost actualizată și va fi salvată odată ce salvați sondajul.",
|
||||
"follow_ups_new": "Follow-up nou",
|
||||
"follow_ups_upgrade_button_text": "Actualizați pentru a activa urmărările",
|
||||
"form_styling": "Stilizare formular",
|
||||
"formbricks_sdk_is_not_connected": "SDK Formbricks nu este conectat",
|
||||
"four_points": "4 puncte",
|
||||
"heading": "Titlu",
|
||||
@@ -1659,6 +1663,7 @@
|
||||
"survey_completed_subheading": "Acest sondaj gratuit și open-source a fost închis",
|
||||
"survey_display_settings": "Setări de afișare a sondajului",
|
||||
"survey_placement": "Amplasarea sondajului",
|
||||
"survey_styling": "Stilizare formular",
|
||||
"survey_trigger": "Declanșator sondaj",
|
||||
"switch_multi_language_on_to_get_started": "Activați opțiunea multi-limbă pentru a începe 👉",
|
||||
"target_block_not_found": "Blocul țintă nu a fost găsit",
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"days": "дни",
|
||||
"default": "По умолчанию",
|
||||
"delete": "Удалить",
|
||||
"delete_what": "Удалить {deleteWhat}",
|
||||
"description": "Описание",
|
||||
"dev_env": "Dev Environment",
|
||||
"development": "Разработка",
|
||||
@@ -225,7 +226,9 @@
|
||||
"failed_to_copy_to_clipboard": "Не удалось скопировать в буфер обмена",
|
||||
"failed_to_load_organizations": "Не удалось загрузить организации",
|
||||
"failed_to_load_workspaces": "Не удалось загрузить рабочие пространства",
|
||||
"filter": "Фильтр",
|
||||
"finish": "Завершить",
|
||||
"first_name": "Имя",
|
||||
"follow_these": "Выполните следующие действия",
|
||||
"formbricks_version": "Версия Formbricks",
|
||||
"full_name": "Полное имя",
|
||||
@@ -238,6 +241,7 @@
|
||||
"hidden_field": "Скрытое поле",
|
||||
"hidden_fields": "Скрытые поля",
|
||||
"hide_column": "Скрыть столбец",
|
||||
"id": "ID",
|
||||
"image": "Изображение",
|
||||
"images": "Изображения",
|
||||
"import": "Импорт",
|
||||
@@ -255,6 +259,7 @@
|
||||
"key": "Ключ",
|
||||
"label": "Метка",
|
||||
"language": "Язык",
|
||||
"last_name": "Фамилия",
|
||||
"learn_more": "Подробнее",
|
||||
"license_expired": "License Expired",
|
||||
"light_overlay": "Светлый оверлей",
|
||||
@@ -1077,7 +1082,7 @@
|
||||
"email_customization_preview_email_heading": "Привет, {userName}",
|
||||
"email_customization_preview_email_text": "Это предварительный просмотр письма, чтобы показать, какой логотип будет отображаться в письмах.",
|
||||
"error_deleting_organization_please_try_again": "Ошибка при удалении организации. Пожалуйста, попробуйте ещё раз.",
|
||||
"from_your_organization": "из вашей организации",
|
||||
"from_your_organization": "{memberName} из вашей организации",
|
||||
"invitation_sent_once_more": "Приглашение отправлено ещё раз.",
|
||||
"invite_deleted_successfully": "Приглашение успешно удалено",
|
||||
"invite_expires_on": "Приглашение истекает {date}",
|
||||
@@ -1440,7 +1445,6 @@
|
||||
"follow_ups_modal_updated_successfull_toast": "Фоллоу-ап обновлён и будет сохранён после сохранения опроса.",
|
||||
"follow_ups_new": "Новый фоллоу-ап",
|
||||
"follow_ups_upgrade_button_text": "Обновите тариф для активации фоллоу-апов",
|
||||
"form_styling": "Оформление формы",
|
||||
"formbricks_sdk_is_not_connected": "Formbricks SDK не подключён",
|
||||
"four_points": "4 балла",
|
||||
"heading": "Заголовок",
|
||||
@@ -1659,6 +1663,7 @@
|
||||
"survey_completed_subheading": "Этот бесплатный и открытый опрос был закрыт",
|
||||
"survey_display_settings": "Настройки отображения опроса",
|
||||
"survey_placement": "Размещение опроса",
|
||||
"survey_styling": "Оформление формы",
|
||||
"survey_trigger": "Триггер опроса",
|
||||
"switch_multi_language_on_to_get_started": "Включите многоязычный режим, чтобы начать 👉",
|
||||
"target_block_not_found": "Целевой блок не найден",
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"days": "dagar",
|
||||
"default": "Standard",
|
||||
"delete": "Ta bort",
|
||||
"delete_what": "Ta bort {deleteWhat}",
|
||||
"description": "Beskrivning",
|
||||
"dev_env": "Utvecklingsmiljö",
|
||||
"development": "Utveckling",
|
||||
@@ -225,7 +226,9 @@
|
||||
"failed_to_copy_to_clipboard": "Misslyckades att kopiera till urklipp",
|
||||
"failed_to_load_organizations": "Misslyckades att ladda organisationer",
|
||||
"failed_to_load_workspaces": "Det gick inte att ladda arbetsytor",
|
||||
"filter": "Filter",
|
||||
"finish": "Slutför",
|
||||
"first_name": "Förnamn",
|
||||
"follow_these": "Följ dessa",
|
||||
"formbricks_version": "Formbricks-version",
|
||||
"full_name": "Fullständigt namn",
|
||||
@@ -238,6 +241,7 @@
|
||||
"hidden_field": "Dolt fält",
|
||||
"hidden_fields": "Dolda fält",
|
||||
"hide_column": "Dölj kolumn",
|
||||
"id": "ID",
|
||||
"image": "Bild",
|
||||
"images": "Bilder",
|
||||
"import": "Importera",
|
||||
@@ -255,6 +259,7 @@
|
||||
"key": "Nyckel",
|
||||
"label": "Etikett",
|
||||
"language": "Språk",
|
||||
"last_name": "Efternamn",
|
||||
"learn_more": "Läs mer",
|
||||
"license_expired": "License Expired",
|
||||
"light_overlay": "Ljust överlägg",
|
||||
@@ -1440,7 +1445,6 @@
|
||||
"follow_ups_modal_updated_successfull_toast": "Uppföljning uppdaterad och sparas när du sparar enkäten.",
|
||||
"follow_ups_new": "Ny uppföljning",
|
||||
"follow_ups_upgrade_button_text": "Uppgradera för att aktivera uppföljningar",
|
||||
"form_styling": "Formulärstil",
|
||||
"formbricks_sdk_is_not_connected": "Formbricks SDK är inte anslutet",
|
||||
"four_points": "4 poäng",
|
||||
"heading": "Rubrik",
|
||||
@@ -1659,6 +1663,7 @@
|
||||
"survey_completed_subheading": "Denna gratis och öppenkällkodsenkät har stängts",
|
||||
"survey_display_settings": "Visningsinställningar för enkät",
|
||||
"survey_placement": "Enkätplacering",
|
||||
"survey_styling": "Formulärstil",
|
||||
"survey_trigger": "Enkätutlösare",
|
||||
"switch_multi_language_on_to_get_started": "Slå på flerspråkighet för att komma igång 👉",
|
||||
"target_block_not_found": "Målblock hittades inte",
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"days": "天",
|
||||
"default": "默认",
|
||||
"delete": "删除",
|
||||
"delete_what": "删除{deleteWhat}",
|
||||
"description": "描述",
|
||||
"dev_env": "开发 环境",
|
||||
"development": "开发环境",
|
||||
@@ -225,7 +226,9 @@
|
||||
"failed_to_copy_to_clipboard": "复制到剪贴板失败",
|
||||
"failed_to_load_organizations": "加载组织失败",
|
||||
"failed_to_load_workspaces": "加载工作区失败",
|
||||
"filter": "筛选",
|
||||
"finish": "完成",
|
||||
"first_name": "名字",
|
||||
"follow_these": "遵循 这些",
|
||||
"formbricks_version": "Formbricks 版本",
|
||||
"full_name": "全名",
|
||||
@@ -238,6 +241,7 @@
|
||||
"hidden_field": "隐藏 字段",
|
||||
"hidden_fields": "隐藏 字段",
|
||||
"hide_column": "隐藏 列",
|
||||
"id": "ID",
|
||||
"image": "图片",
|
||||
"images": "图片",
|
||||
"import": "导入",
|
||||
@@ -255,6 +259,7 @@
|
||||
"key": "键",
|
||||
"label": "标签",
|
||||
"language": "语言",
|
||||
"last_name": "姓",
|
||||
"learn_more": "了解 更多",
|
||||
"license_expired": "License Expired",
|
||||
"light_overlay": "浅色遮罩层",
|
||||
@@ -1077,7 +1082,7 @@
|
||||
"email_customization_preview_email_heading": "嘿 {userName}",
|
||||
"email_customization_preview_email_text": "这 是 一封 电子邮件 预览,展示 哪个 徽标 将在 电子邮件 中 渲染。",
|
||||
"error_deleting_organization_please_try_again": "删除 组织时 出错 。 请重试 。",
|
||||
"from_your_organization": "来自你的组织",
|
||||
"from_your_organization": "来自您组织的{memberName}",
|
||||
"invitation_sent_once_more": "再次发送邀请。",
|
||||
"invite_deleted_successfully": "邀请 删除 成功",
|
||||
"invite_expires_on": "邀请将于 {date} 过期",
|
||||
@@ -1440,7 +1445,6 @@
|
||||
"follow_ups_modal_updated_successfull_toast": "后续 操作 已 更新, 并且 在 你 保存 调查 后 将 被 保存。",
|
||||
"follow_ups_new": "新的跟进",
|
||||
"follow_ups_upgrade_button_text": "升级 以启用 跟进",
|
||||
"form_styling": "表单 样式",
|
||||
"formbricks_sdk_is_not_connected": "Formbricks SDK 未连接",
|
||||
"four_points": "4 分",
|
||||
"heading": "标题",
|
||||
@@ -1659,6 +1663,7 @@
|
||||
"survey_completed_subheading": "此 免费 & 开源 调查 已 关闭",
|
||||
"survey_display_settings": "调查显示设置",
|
||||
"survey_placement": "调查 放置",
|
||||
"survey_styling": "表单 样式",
|
||||
"survey_trigger": "调查 触发",
|
||||
"switch_multi_language_on_to_get_started": "开启多语言以开始使用 👉",
|
||||
"target_block_not_found": "未找到目标区块",
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"days": "天",
|
||||
"default": "預設",
|
||||
"delete": "刪除",
|
||||
"delete_what": "刪除{deleteWhat}",
|
||||
"description": "描述",
|
||||
"dev_env": "開發環境",
|
||||
"development": "開發",
|
||||
@@ -225,7 +226,9 @@
|
||||
"failed_to_copy_to_clipboard": "無法複製到剪貼簿",
|
||||
"failed_to_load_organizations": "無法載入組織",
|
||||
"failed_to_load_workspaces": "載入工作區失敗",
|
||||
"filter": "篩選",
|
||||
"finish": "完成",
|
||||
"first_name": "名字",
|
||||
"follow_these": "按照這些步驟",
|
||||
"formbricks_version": "Formbricks 版本",
|
||||
"full_name": "全名",
|
||||
@@ -238,6 +241,7 @@
|
||||
"hidden_field": "隱藏欄位",
|
||||
"hidden_fields": "隱藏欄位",
|
||||
"hide_column": "隱藏欄位",
|
||||
"id": "ID",
|
||||
"image": "圖片",
|
||||
"images": "圖片",
|
||||
"import": "匯入",
|
||||
@@ -255,6 +259,7 @@
|
||||
"key": "金鑰",
|
||||
"label": "標籤",
|
||||
"language": "語言",
|
||||
"last_name": "姓氏",
|
||||
"learn_more": "瞭解更多",
|
||||
"license_expired": "License Expired",
|
||||
"light_overlay": "淺色覆蓋",
|
||||
@@ -1440,7 +1445,6 @@
|
||||
"follow_ups_modal_updated_successfull_toast": "後續 動作 已 更新 並 將 在 你 儲存 調查 後 儲存",
|
||||
"follow_ups_new": "新增後續追蹤",
|
||||
"follow_ups_upgrade_button_text": "升級以啟用後續追蹤",
|
||||
"form_styling": "表單樣式設定",
|
||||
"formbricks_sdk_is_not_connected": "Formbricks SDK 未連線",
|
||||
"four_points": "4 分",
|
||||
"heading": "標題",
|
||||
@@ -1659,6 +1663,7 @@
|
||||
"survey_completed_subheading": "此免費且開源的問卷已關閉",
|
||||
"survey_display_settings": "問卷顯示設定",
|
||||
"survey_placement": "問卷位置",
|
||||
"survey_styling": "表單樣式設定",
|
||||
"survey_trigger": "問卷觸發器",
|
||||
"switch_multi_language_on_to_get_started": "請開啟多語言功能以開始使用 👉",
|
||||
"target_block_not_found": "找不到目標區塊",
|
||||
|
||||
@@ -99,7 +99,7 @@ export const ContactControlBar = ({
|
||||
<DeleteDialog
|
||||
open={deleteDialogOpen}
|
||||
setOpen={setDeleteDialogOpen}
|
||||
deleteWhat="person"
|
||||
deleteWhat={t("common.person")}
|
||||
onDelete={handleDeletePerson}
|
||||
isDeleting={isDeletingPerson}
|
||||
text={
|
||||
|
||||
@@ -66,7 +66,7 @@ export const DeleteContactButton = ({
|
||||
<DeleteDialog
|
||||
open={deleteDialogOpen}
|
||||
setOpen={setDeleteDialogOpen}
|
||||
deleteWhat="person"
|
||||
deleteWhat={t("common.person")}
|
||||
onDelete={handleDeletePerson}
|
||||
isDeleting={isDeletingPerson}
|
||||
text={
|
||||
|
||||
@@ -52,54 +52,41 @@ export const getPersonSegmentIds = async (
|
||||
return [];
|
||||
}
|
||||
|
||||
// Phase 1: Build all Prisma where clauses concurrently.
|
||||
// This converts segment filters into where clauses without per-contact DB queries.
|
||||
const segmentWithClauses = await Promise.all(
|
||||
segments.map(async (segment) => {
|
||||
const filters = segment.filters as TBaseFilters | null;
|
||||
|
||||
if (!filters || filters.length === 0) {
|
||||
return { segmentId: segment.id, whereClause: {} as Prisma.ContactWhereInput };
|
||||
}
|
||||
|
||||
const queryResult = await segmentFilterToPrismaQuery(segment.id, filters, environmentId, deviceType);
|
||||
|
||||
if (!queryResult.ok) {
|
||||
logger.warn(
|
||||
{ segmentId: segment.id, environmentId, error: queryResult.error },
|
||||
"Failed to build Prisma query for segment"
|
||||
);
|
||||
return { segmentId: segment.id, whereClause: null };
|
||||
}
|
||||
|
||||
return { segmentId: segment.id, whereClause: queryResult.data.whereClause };
|
||||
})
|
||||
);
|
||||
|
||||
// Separate segments into: always-match (no filters), needs-DB-check, and failed-to-build
|
||||
// Phase 1: Build WHERE clauses sequentially to avoid connection pool contention.
|
||||
// segmentFilterToPrismaQuery can itself hit the DB (e.g. unmigrated-row checks),
|
||||
// so running all builds concurrently would saturate the pool.
|
||||
const alwaysMatchIds: string[] = [];
|
||||
const toCheck: { segmentId: string; whereClause: Prisma.ContactWhereInput }[] = [];
|
||||
const dbChecks: { segmentId: string; whereClause: Prisma.ContactWhereInput }[] = [];
|
||||
|
||||
for (const item of segmentWithClauses) {
|
||||
if (item.whereClause === null) {
|
||||
for (const segment of segments) {
|
||||
const filters = segment.filters as TBaseFilters;
|
||||
|
||||
if (!filters?.length) {
|
||||
alwaysMatchIds.push(segment.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Object.keys(item.whereClause).length === 0) {
|
||||
alwaysMatchIds.push(item.segmentId);
|
||||
} else {
|
||||
toCheck.push({ segmentId: item.segmentId, whereClause: item.whereClause });
|
||||
const queryResult = await segmentFilterToPrismaQuery(segment.id, filters, environmentId, deviceType);
|
||||
|
||||
if (!queryResult.ok) {
|
||||
logger.warn(
|
||||
{ segmentId: segment.id, environmentId, error: queryResult.error },
|
||||
"Failed to build Prisma query for segment, skipping"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
dbChecks.push({ segmentId: segment.id, whereClause: queryResult.data.whereClause });
|
||||
}
|
||||
|
||||
if (toCheck.length === 0) {
|
||||
if (dbChecks.length === 0) {
|
||||
return alwaysMatchIds;
|
||||
}
|
||||
|
||||
// Phase 2: Batch all contact-match checks into a single DB transaction.
|
||||
// Replaces N individual findFirst queries with one batched round-trip.
|
||||
const batchResults = await prisma.$transaction(
|
||||
toCheck.map(({ whereClause }) =>
|
||||
// Phase 2: Execute all membership checks in a single transaction.
|
||||
// Uses one connection instead of N concurrent ones, eliminating pool contention.
|
||||
const txResults = await prisma.$transaction(
|
||||
dbChecks.map(({ whereClause }) =>
|
||||
prisma.contact.findFirst({
|
||||
where: { id: contactId, ...whereClause },
|
||||
select: { id: true },
|
||||
@@ -107,17 +94,12 @@ export const getPersonSegmentIds = async (
|
||||
)
|
||||
);
|
||||
|
||||
// Phase 3: Collect matching segment IDs
|
||||
const dbMatchIds = toCheck.filter((_, i) => batchResults[i] !== null).map(({ segmentId }) => segmentId);
|
||||
const matchedIds = dbChecks.filter((_, i) => txResults[i] !== null).map(({ segmentId }) => segmentId);
|
||||
|
||||
return [...alwaysMatchIds, ...dbMatchIds];
|
||||
return [...alwaysMatchIds, ...matchedIds];
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
{
|
||||
environmentId,
|
||||
contactId,
|
||||
error,
|
||||
},
|
||||
{ environmentId, contactId, error },
|
||||
"Failed to get person segment IDs, returning empty array"
|
||||
);
|
||||
return [];
|
||||
|
||||
-139
@@ -1,139 +0,0 @@
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { TJsPersonState } from "@formbricks/types/js";
|
||||
import { getPersonSegmentIds } from "./segments";
|
||||
import { getUserState } from "./user-state";
|
||||
|
||||
vi.mock("@formbricks/database", () => ({
|
||||
prisma: {
|
||||
contact: {
|
||||
findUniqueOrThrow: vi.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("./segments", () => ({
|
||||
getPersonSegmentIds: vi.fn(),
|
||||
}));
|
||||
|
||||
const mockEnvironmentId = "test-environment-id";
|
||||
const mockUserId = "test-user-id";
|
||||
const mockContactId = "test-contact-id";
|
||||
const mockDevice = "desktop";
|
||||
|
||||
describe("getUserState", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test("should return user state with empty responses and displays", async () => {
|
||||
const mockContactData = {
|
||||
id: mockContactId,
|
||||
responses: [],
|
||||
displays: [],
|
||||
};
|
||||
vi.mocked(prisma.contact.findUniqueOrThrow).mockResolvedValue(mockContactData as any);
|
||||
vi.mocked(getPersonSegmentIds).mockResolvedValue(["segment1"]);
|
||||
|
||||
const result = await getUserState({
|
||||
environmentId: mockEnvironmentId,
|
||||
userId: mockUserId,
|
||||
contactId: mockContactId,
|
||||
device: mockDevice,
|
||||
});
|
||||
|
||||
expect(prisma.contact.findUniqueOrThrow).toHaveBeenCalledWith({
|
||||
where: { id: mockContactId },
|
||||
select: {
|
||||
id: true,
|
||||
responses: {
|
||||
select: { surveyId: true },
|
||||
},
|
||||
displays: {
|
||||
select: { surveyId: true, createdAt: true },
|
||||
orderBy: { createdAt: "desc" },
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(getPersonSegmentIds).toHaveBeenCalledWith(
|
||||
mockEnvironmentId,
|
||||
mockContactId,
|
||||
mockUserId,
|
||||
mockDevice
|
||||
);
|
||||
expect(result).toEqual<TJsPersonState["data"]>({
|
||||
contactId: mockContactId,
|
||||
userId: mockUserId,
|
||||
segments: ["segment1"],
|
||||
displays: [],
|
||||
responses: [],
|
||||
lastDisplayAt: null,
|
||||
});
|
||||
});
|
||||
|
||||
test("should return user state with responses and displays, and sort displays by createdAt", async () => {
|
||||
const mockDate1 = new Date("2023-01-01T00:00:00.000Z");
|
||||
const mockDate2 = new Date("2023-01-02T00:00:00.000Z");
|
||||
|
||||
const mockContactData = {
|
||||
id: mockContactId,
|
||||
responses: [{ surveyId: "survey1" }, { surveyId: "survey2" }],
|
||||
displays: [
|
||||
{ surveyId: "survey4", createdAt: mockDate2 }, // most recent (already sorted by desc)
|
||||
{ surveyId: "survey3", createdAt: mockDate1 },
|
||||
],
|
||||
};
|
||||
vi.mocked(prisma.contact.findUniqueOrThrow).mockResolvedValue(mockContactData as any);
|
||||
vi.mocked(getPersonSegmentIds).mockResolvedValue(["segment2", "segment3"]);
|
||||
|
||||
const result = await getUserState({
|
||||
environmentId: mockEnvironmentId,
|
||||
userId: mockUserId,
|
||||
contactId: mockContactId,
|
||||
device: mockDevice,
|
||||
});
|
||||
|
||||
expect(result).toEqual<TJsPersonState["data"]>({
|
||||
contactId: mockContactId,
|
||||
userId: mockUserId,
|
||||
segments: ["segment2", "segment3"],
|
||||
displays: [
|
||||
{ surveyId: "survey4", createdAt: mockDate2 },
|
||||
{ surveyId: "survey3", createdAt: mockDate1 },
|
||||
],
|
||||
responses: ["survey1", "survey2"],
|
||||
lastDisplayAt: mockDate2,
|
||||
});
|
||||
});
|
||||
|
||||
test("should handle empty arrays from prisma", async () => {
|
||||
// This case tests with proper empty arrays instead of null
|
||||
const mockContactData = {
|
||||
id: mockContactId,
|
||||
responses: [],
|
||||
displays: [],
|
||||
};
|
||||
vi.mocked(prisma.contact.findUniqueOrThrow).mockResolvedValue(mockContactData as any);
|
||||
vi.mocked(getPersonSegmentIds).mockResolvedValue([]);
|
||||
|
||||
const result = await getUserState({
|
||||
environmentId: mockEnvironmentId,
|
||||
userId: mockUserId,
|
||||
contactId: mockContactId,
|
||||
device: mockDevice,
|
||||
});
|
||||
|
||||
expect(result).toEqual<TJsPersonState["data"]>({
|
||||
contactId: mockContactId,
|
||||
userId: mockUserId,
|
||||
segments: [],
|
||||
displays: [],
|
||||
responses: [],
|
||||
lastDisplayAt: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,80 +0,0 @@
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { TJsPersonState } from "@formbricks/types/js";
|
||||
import { getPersonSegmentIds } from "./segments";
|
||||
|
||||
/**
|
||||
* Optimized single query to get all user state data
|
||||
* Replaces multiple separate queries with one efficient query
|
||||
*/
|
||||
const getUserStateDataOptimized = async (contactId: string) => {
|
||||
return prisma.contact.findUniqueOrThrow({
|
||||
where: { id: contactId },
|
||||
select: {
|
||||
id: true,
|
||||
responses: {
|
||||
select: { surveyId: true },
|
||||
},
|
||||
displays: {
|
||||
select: {
|
||||
surveyId: true,
|
||||
createdAt: true,
|
||||
},
|
||||
orderBy: { createdAt: "desc" },
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Optimized user state fetcher without caching
|
||||
* Uses single database query and efficient data processing
|
||||
* NO CACHING - user state changes frequently with contact updates
|
||||
*
|
||||
* @param environmentId - The environment id
|
||||
* @param userId - The user id
|
||||
* @param device - The device type
|
||||
* @returns The person state
|
||||
* @throws {ValidationError} - If the input is invalid
|
||||
* @throws {ResourceNotFoundError} - If the environment or organization is not found
|
||||
*/
|
||||
export const getUserState = async ({
|
||||
environmentId,
|
||||
userId,
|
||||
contactId,
|
||||
device,
|
||||
}: {
|
||||
environmentId: string;
|
||||
userId: string;
|
||||
contactId: string;
|
||||
device: "phone" | "desktop";
|
||||
}): Promise<TJsPersonState["data"]> => {
|
||||
// Single optimized query for all contact data
|
||||
const contactData = await getUserStateDataOptimized(contactId);
|
||||
|
||||
// Get segments using Prisma-based evaluation (no attributes needed - fetched from DB)
|
||||
const segments = await getPersonSegmentIds(environmentId, contactId, userId, device);
|
||||
|
||||
// Process displays efficiently
|
||||
const displays = (contactData.displays ?? []).map((display) => ({
|
||||
surveyId: display.surveyId,
|
||||
createdAt: display.createdAt,
|
||||
}));
|
||||
|
||||
// Get latest display date
|
||||
const lastDisplayAt =
|
||||
contactData.displays && contactData.displays.length > 0 ? contactData.displays[0].createdAt : null;
|
||||
|
||||
// Process responses efficiently
|
||||
const responses = (contactData.responses ?? []).map((response) => response.surveyId);
|
||||
|
||||
const userState: TJsPersonState["data"] = {
|
||||
contactId,
|
||||
userId,
|
||||
segments,
|
||||
displays,
|
||||
responses,
|
||||
lastDisplayAt,
|
||||
};
|
||||
|
||||
return userState;
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
import { getLocale } from "@/lingodotdev/language";
|
||||
import { getTranslate } from "@/lingodotdev/server";
|
||||
import { ContactsPageLayout } from "@/modules/ee/contacts/components/contacts-page-layout";
|
||||
import { getContactAttributeKeys } from "@/modules/ee/contacts/lib/contact-attribute-keys";
|
||||
import { getIsContactsEnabled } from "@/modules/ee/license-check/lib/utils";
|
||||
@@ -13,7 +14,7 @@ export const AttributesPage = async ({
|
||||
}) => {
|
||||
const params = await paramsProps;
|
||||
const locale = await getLocale();
|
||||
|
||||
const t = await getTranslate();
|
||||
const [{ isReadOnly }, contactAttributeKeys] = await Promise.all([
|
||||
getEnvironmentAuth(params.environmentId),
|
||||
getContactAttributeKeys(params.environmentId),
|
||||
@@ -23,7 +24,7 @@ export const AttributesPage = async ({
|
||||
|
||||
return (
|
||||
<ContactsPageLayout
|
||||
pageTitle="Contacts"
|
||||
pageTitle={t("common.contacts")}
|
||||
activeId="attributes"
|
||||
environmentId={params.environmentId}
|
||||
isContactsEnabled={isContactsEnabled}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
import { TFunction } from "i18next";
|
||||
import { formatAttributeValue } from "@/modules/ee/contacts/lib/format-attribute-value";
|
||||
import { getSelectionColumn } from "@/modules/ui/components/data-table";
|
||||
import { HighlightedText } from "@/modules/ui/components/highlighted-text";
|
||||
@@ -10,12 +11,13 @@ import { TContactTableData } from "../types/contact";
|
||||
export const generateContactTableColumns = (
|
||||
searchValue: string,
|
||||
data: TContactTableData[],
|
||||
isReadOnly: boolean
|
||||
isReadOnly: boolean,
|
||||
t: TFunction
|
||||
): ColumnDef<TContactTableData>[] => {
|
||||
const userColumn: ColumnDef<TContactTableData> = {
|
||||
id: "contactsTableUser",
|
||||
accessorKey: "contactsTableUser",
|
||||
header: "ID",
|
||||
header: t("common.id"),
|
||||
cell: ({ row }) => {
|
||||
const contactId = row.original.id;
|
||||
return <HighlightedText value={contactId} searchValue={searchValue} />;
|
||||
@@ -25,7 +27,7 @@ export const generateContactTableColumns = (
|
||||
const userIdColumn: ColumnDef<TContactTableData> = {
|
||||
id: "userId",
|
||||
accessorKey: "userId",
|
||||
header: "User ID",
|
||||
header: t("common.user_id"),
|
||||
cell: ({ row }) => {
|
||||
const userId = row.original.userId;
|
||||
return <IdBadge id={userId} />;
|
||||
@@ -35,7 +37,7 @@ export const generateContactTableColumns = (
|
||||
const emailColumn: ColumnDef<TContactTableData> = {
|
||||
id: "email",
|
||||
accessorKey: "email",
|
||||
header: "Email",
|
||||
header: t("common.email"),
|
||||
cell: ({ row }) => {
|
||||
const email = row.original.email;
|
||||
if (email) {
|
||||
@@ -47,7 +49,7 @@ export const generateContactTableColumns = (
|
||||
const firstNameColumn: ColumnDef<TContactTableData> = {
|
||||
id: "firstName",
|
||||
accessorKey: "firstName",
|
||||
header: "First Name",
|
||||
header: t("common.first_name"),
|
||||
cell: ({ row }) => {
|
||||
const firstName = row.original.firstName;
|
||||
return <HighlightedText value={firstName} searchValue={searchValue} />;
|
||||
@@ -57,7 +59,7 @@ export const generateContactTableColumns = (
|
||||
const lastNameColumn: ColumnDef<TContactTableData> = {
|
||||
id: "lastName",
|
||||
accessorKey: "lastName",
|
||||
header: "Last Name",
|
||||
header: t("common.last_name"),
|
||||
cell: ({ row }) => {
|
||||
const lastName = row.original.lastName;
|
||||
return <HighlightedText value={lastName} searchValue={searchValue} />;
|
||||
|
||||
@@ -71,7 +71,7 @@ export const ContactsTable = ({
|
||||
|
||||
// Generate columns
|
||||
const columns = useMemo(() => {
|
||||
return generateContactTableColumns(searchValue, data, isReadOnly);
|
||||
return generateContactTableColumns(searchValue, data, isReadOnly, t);
|
||||
}, [searchValue, data, isReadOnly]);
|
||||
|
||||
// Load saved settings from localStorage
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
import { format, formatDistanceToNow } from "date-fns";
|
||||
import { TFunction } from "i18next";
|
||||
import { UsersIcon } from "lucide-react";
|
||||
import { TSegmentWithSurveyNames } from "@formbricks/types/segment";
|
||||
|
||||
export const generateSegmentTableColumns = (): ColumnDef<TSegmentWithSurveyNames>[] => {
|
||||
export const generateSegmentTableColumns = (t: TFunction): ColumnDef<TSegmentWithSurveyNames>[] => {
|
||||
const titleColumn: ColumnDef<TSegmentWithSurveyNames> = {
|
||||
id: "title",
|
||||
accessorKey: "title",
|
||||
header: "Title",
|
||||
header: t("common.title"),
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<div className="flex items-center gap-4">
|
||||
@@ -30,7 +31,7 @@ export const generateSegmentTableColumns = (): ColumnDef<TSegmentWithSurveyNames
|
||||
const updatedAtColumn: ColumnDef<TSegmentWithSurveyNames> = {
|
||||
id: "updatedAt",
|
||||
accessorKey: "updatedAt",
|
||||
header: "Updated",
|
||||
header: t("common.updated_at"),
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<span className="text-sm text-slate-900">
|
||||
@@ -43,7 +44,7 @@ export const generateSegmentTableColumns = (): ColumnDef<TSegmentWithSurveyNames
|
||||
const createdAtColumn: ColumnDef<TSegmentWithSurveyNames> = {
|
||||
id: "createdAt",
|
||||
accessorKey: "createdAt",
|
||||
header: "Created",
|
||||
header: t("common.created_at"),
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<span className="text-sm text-slate-900">{format(row.original.createdAt, "do 'of' MMMM, yyyy")}</span>
|
||||
|
||||
@@ -26,7 +26,7 @@ export function SegmentTable({
|
||||
const [editingSegment, setEditingSegment] = useState<TSegmentWithSurveyNames | null>(null);
|
||||
|
||||
const columns = useMemo(() => {
|
||||
return generateSegmentTableColumns();
|
||||
return generateSegmentTableColumns(t);
|
||||
}, []);
|
||||
|
||||
const table = useReactTable({
|
||||
|
||||
@@ -32,7 +32,7 @@ export const SegmentsPage = async ({
|
||||
|
||||
return (
|
||||
<ContactsPageLayout
|
||||
pageTitle="Contacts"
|
||||
pageTitle={t("common.contacts")}
|
||||
activeId="segments"
|
||||
environmentId={params.environmentId}
|
||||
isContactsEnabled={isContactsEnabled}
|
||||
|
||||
+1
-1
@@ -168,7 +168,7 @@ export const MemberActions = ({ organization, member, invite, showDeleteButton }
|
||||
<DeleteDialog
|
||||
open={isDeleteMemberModalOpen}
|
||||
setOpen={setDeleteMemberModalOpen}
|
||||
deleteWhat={`${memberName} ${t("environments.settings.general.from_your_organization")}`}
|
||||
deleteWhat={t("environments.settings.general.from_your_organization", { memberName })}
|
||||
onDelete={handleDeleteMember}
|
||||
isDeleting={isDeleting}
|
||||
text={t("environments.settings.general.delete_member_confirmation")}
|
||||
|
||||
@@ -89,7 +89,7 @@ export const DeleteProjectRender = ({
|
||||
)}
|
||||
|
||||
<DeleteDialog
|
||||
deleteWhat="Workspace"
|
||||
deleteWhat={t("environments.settings.domain.workspace")}
|
||||
open={isDeleteDialogOpen}
|
||||
setOpen={setIsDeleteDialogOpen}
|
||||
onDelete={handleDeleteProject}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { SettingsCard } from "@/app/(app)/environments/[environmentId]/settings/components/SettingsCard";
|
||||
import { IS_DEVELOPMENT, IS_FORMBRICKS_CLOUD } from "@/lib/constants";
|
||||
import { IS_FORMBRICKS_CLOUD } from "@/lib/constants";
|
||||
import { getProjects } from "@/lib/project/service";
|
||||
import { getTranslate } from "@/lingodotdev/server";
|
||||
import { getEnvironmentAuth } from "@/modules/environments/lib/utils";
|
||||
@@ -7,7 +7,6 @@ import { ProjectConfigNavigation } from "@/modules/projects/settings/components/
|
||||
import { IdBadge } from "@/modules/ui/components/id-badge";
|
||||
import { PageContentWrapper } from "@/modules/ui/components/page-content-wrapper";
|
||||
import { PageHeader } from "@/modules/ui/components/page-header";
|
||||
import packageJson from "@/package.json";
|
||||
import { CustomScriptsForm } from "./components/custom-scripts-form";
|
||||
import { DeleteProject } from "./components/delete-project";
|
||||
import { EditProjectNameForm } from "./components/edit-project-name-form";
|
||||
@@ -59,9 +58,6 @@ export const GeneralSettingsPage = async (props: { params: Promise<{ environment
|
||||
</SettingsCard>
|
||||
<div className="space-y-2">
|
||||
<IdBadge id={project.id} label={t("common.workspace_id")} variant="column" />
|
||||
{!IS_FORMBRICKS_CLOUD && !IS_DEVELOPMENT && (
|
||||
<IdBadge id={packageJson.version} label={t("common.formbricks_version")} variant="column" />
|
||||
)}
|
||||
</div>
|
||||
</PageContentWrapper>
|
||||
);
|
||||
|
||||
@@ -52,7 +52,7 @@ export const ProjectLookSettingsLoading = () => {
|
||||
<div className="w-full rounded-lg border border-slate-300 bg-white">
|
||||
<div className="flex flex-col p-4">
|
||||
<h2 className="text-sm font-semibold text-slate-700">
|
||||
{t("environments.surveys.edit.form_styling")}
|
||||
{t("environments.surveys.edit.survey_styling")}
|
||||
</h2>
|
||||
<p className="mt-1 text-xs text-slate-500">
|
||||
{t("environments.surveys.edit.style_the_question_texts_descriptions_and_input_fields")}
|
||||
@@ -149,7 +149,7 @@ export const ProjectLookSettingsLoading = () => {
|
||||
<div className={cn("absolute bottom-3 h-16 w-16 rounded bg-slate-700 sm:right-3")}></div>
|
||||
</div>
|
||||
</div>
|
||||
<Button className="pointer-events-none mt-4 animate-pulse cursor-not-allowed bg-slate-200 select-none">
|
||||
<Button className="pointer-events-none mt-4 animate-pulse cursor-not-allowed select-none bg-slate-200">
|
||||
{t("common.loading")}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -159,7 +159,7 @@ export const ProjectLookSettingsLoading = () => {
|
||||
title="Formbricks Signature"
|
||||
description="We love your support but understand if you toggle it off.">
|
||||
<div className="w-full items-center">
|
||||
<div className="pointer-events-none flex cursor-not-allowed items-center space-x-2 select-none">
|
||||
<div className="pointer-events-none flex cursor-not-allowed select-none items-center space-x-2">
|
||||
<Switch id="signature" checked={false} />
|
||||
<Label htmlFor="signature">{t("environments.workspace.look.show_powered_by_formbricks")}</Label>
|
||||
</div>
|
||||
|
||||
@@ -67,7 +67,7 @@ export const FormStylingSettings = ({
|
||||
|
||||
<div>
|
||||
<p className={cn("font-semibold text-slate-800", isSettingsPage ? "text-sm" : "text-base")}>
|
||||
{t("environments.surveys.edit.form_styling")}
|
||||
{t("environments.surveys.edit.survey_styling")}
|
||||
</p>
|
||||
<p className={cn("mt-1 text-slate-500", isSettingsPage ? "text-xs" : "text-sm")}>
|
||||
{t("environments.surveys.edit.style_the_question_texts_descriptions_and_input_fields")}
|
||||
|
||||
@@ -13,9 +13,6 @@ interface CustomScriptsInjectorProps {
|
||||
* Injects custom HTML scripts into the document head for link surveys.
|
||||
* Supports merging project and survey scripts or replacing project scripts with survey scripts.
|
||||
*
|
||||
* User-provided scripts are wrapped in try-catch blocks to prevent runtime errors
|
||||
* (e.g., calls to deprecated browser APIs) from breaking the survey experience.
|
||||
*
|
||||
* @param projectScripts - Scripts configured at the workspace/project level
|
||||
* @param surveyScripts - Scripts configured at the survey level
|
||||
* @param scriptsMode - "add" merges both, "replace" uses only survey scripts
|
||||
@@ -61,21 +58,9 @@ export const CustomScriptsInjector = ({
|
||||
|
||||
// Copy inline script content
|
||||
if (script.textContent) {
|
||||
// Wrap inline scripts in try-catch to prevent user script errors from breaking the survey
|
||||
newScript.textContent = `
|
||||
try {
|
||||
${script.textContent}
|
||||
} catch (error) {
|
||||
console.warn('[Formbricks] Error in custom script:', error);
|
||||
}
|
||||
`;
|
||||
newScript.textContent = script.textContent;
|
||||
}
|
||||
|
||||
// Add error handler for external scripts loaded via src
|
||||
newScript.onerror = (error) => {
|
||||
console.warn("[Formbricks] Error loading external script:", error);
|
||||
};
|
||||
|
||||
document.head.appendChild(newScript);
|
||||
});
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ export const SurveyDropDownMenu = ({
|
||||
|
||||
{!isSurveyCreationDeletionDisabled && (
|
||||
<DeleteDialog
|
||||
deleteWhat="Survey"
|
||||
deleteWhat={t("common.survey")}
|
||||
open={isDeleteDialogOpen}
|
||||
setOpen={setDeleteDialogOpen}
|
||||
onDelete={() => handleDeleteSurvey(survey.id)}
|
||||
|
||||
@@ -48,7 +48,7 @@ export const DeleteDialog = ({
|
||||
<div className="flex items-center gap-2">
|
||||
<CircleAlert className="h-4 w-4" />
|
||||
<div>
|
||||
<DialogTitle>{`${t("common.delete")} ${deleteWhat}`}</DialogTitle>
|
||||
<DialogTitle>{t("common.delete_what", { deleteWhat })}</DialogTitle>
|
||||
<DialogDescription>
|
||||
{t("environments.workspace.general.this_action_cannot_be_undone")}
|
||||
</DialogDescription>
|
||||
|
||||
@@ -54,9 +54,9 @@
|
||||
"@opentelemetry/sdk-node": "0.211.0",
|
||||
"@opentelemetry/sdk-trace-base": "2.5.0",
|
||||
"@opentelemetry/semantic-conventions": "1.38.0",
|
||||
"@prisma/instrumentation": "6.14.0",
|
||||
"@paralleldrive/cuid2": "2.2.2",
|
||||
"@prisma/client": "6.14.0",
|
||||
"@prisma/instrumentation": "6.14.0",
|
||||
"@radix-ui/react-accordion": "1.2.10",
|
||||
"@radix-ui/react-checkbox": "1.3.1",
|
||||
"@radix-ui/react-collapsible": "1.1.10",
|
||||
@@ -114,10 +114,12 @@
|
||||
"prismjs": "1.30.0",
|
||||
"qr-code-styling": "1.9.2",
|
||||
"qrcode": "1.5.4",
|
||||
"react": "19.2.3",
|
||||
"react-calendar": "5.1.0",
|
||||
"react-colorful": "5.6.1",
|
||||
"react-confetti": "6.4.0",
|
||||
"react-day-picker": "9.6.7",
|
||||
"react-dom": "19.2.3",
|
||||
"react-hook-form": "7.56.2",
|
||||
"react-hot-toast": "2.5.2",
|
||||
"react-i18next": "15.7.3",
|
||||
@@ -135,10 +137,8 @@
|
||||
"uuid": "11.1.0",
|
||||
"webpack": "5.99.8",
|
||||
"xlsx": "file:vendor/xlsx-0.20.3.tgz",
|
||||
"zod": "3.24.4",
|
||||
"zod-openapi": "4.2.4",
|
||||
"react": "19.2.3",
|
||||
"react-dom": "19.2.3"
|
||||
"zod": "3.25.76",
|
||||
"zod-openapi": "4.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@formbricks/config-typescript": "workspace:*",
|
||||
|
||||
@@ -50,8 +50,8 @@ test.describe("Survey Styling", async () => {
|
||||
await addCustomStyles.click();
|
||||
}
|
||||
|
||||
// --- Form styling ---
|
||||
await openAccordion(page, "Form styling");
|
||||
// --- Survey styling ---
|
||||
await openAccordion(page, "Survey styling");
|
||||
|
||||
// 1. Headlines & Descriptions
|
||||
await openAccordion(page, "Headlines & Descriptions");
|
||||
@@ -182,7 +182,7 @@ test.describe("Survey Styling", async () => {
|
||||
}
|
||||
|
||||
// Set some non-color properties BEFORE suggesting colors, so we can verify they aren't overwritten
|
||||
await openAccordion(page, "Form styling");
|
||||
await openAccordion(page, "Survey styling");
|
||||
await openAccordion(page, "Inputs");
|
||||
await setDimension(page, "Border Radius", "12");
|
||||
await setDimension(page, "Padding Y", "20");
|
||||
@@ -341,7 +341,7 @@ test.describe("Survey Styling", async () => {
|
||||
}
|
||||
|
||||
// Apply Overrides
|
||||
await openAccordion(page, "Form styling");
|
||||
await openAccordion(page, "Survey styling");
|
||||
await openAccordion(page, "Headlines & Descriptions");
|
||||
|
||||
// Override Headline Color (Blue)
|
||||
|
||||
+6
-2
@@ -99,7 +99,7 @@
|
||||
"xm-and-surveys/surveys/link-surveys/personal-links",
|
||||
"xm-and-surveys/surveys/link-surveys/single-use-links",
|
||||
"xm-and-surveys/surveys/link-surveys/source-tracking",
|
||||
"xm-and-surveys/surveys/link-surveys/start-at-question",
|
||||
"xm-and-surveys/surveys/link-surveys/start-at-block",
|
||||
"xm-and-surveys/surveys/link-surveys/verify-email-before-survey",
|
||||
"xm-and-surveys/surveys/link-surveys/market-research-panel",
|
||||
"xm-and-surveys/surveys/link-surveys/pin-protected-surveys",
|
||||
@@ -516,9 +516,13 @@
|
||||
"source": "/docs/link-surveys/global/schedule-start-end-dates"
|
||||
},
|
||||
{
|
||||
"destination": "/docs/xm-and-surveys/surveys/link-surveys/start-at-question",
|
||||
"destination": "/docs/xm-and-surveys/surveys/link-surveys/start-at-block",
|
||||
"source": "/docs/link-surveys/start-at-question"
|
||||
},
|
||||
{
|
||||
"destination": "/docs/xm-and-surveys/surveys/link-surveys/start-at-block",
|
||||
"source": "/docs/xm-and-surveys/surveys/link-surveys/start-at-question"
|
||||
},
|
||||
{
|
||||
"destination": "/docs/xm-and-surveys/surveys/general-features/metadata",
|
||||
"source": "/docs/link-surveys/global/metadata"
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "Styling Theme"
|
||||
description: "Keep the survey styling consistent over all surveys with a Styling Theme. Customize the colors, fonts, and other styling options to match your brand's aesthetic."
|
||||
description: "Keep the survey styling consistent over all surveys with a Styling Theme. Customize colors, fonts, buttons, inputs, and more to match your brand."
|
||||
icon: "palette"
|
||||
---
|
||||
|
||||
@@ -10,48 +10,114 @@ icon: "palette"
|
||||
uploads](/self-hosting/configuration/file-uploads) before using these features.
|
||||
</Note>
|
||||
|
||||
Keep the survey styling consistent over all surveys with a Styling Theme. Customize the colors, fonts, and other styling options to match your brand's aesthetic.
|
||||
Keep the survey styling consistent over all surveys with a Styling Theme. Customize colors, fonts, buttons, inputs, and other styling options to match your brand's aesthetic.
|
||||
|
||||
## Configuration
|
||||
|
||||
In the left side bar, you find the `Configuration` page. On this page you find the `Look & Feel` section:
|
||||
|
||||

|
||||
/>
|
||||

|
||||
|
||||
## **Styling Options**
|
||||
## Survey styling
|
||||
|
||||
1. **Form Styling:** Customize the survey card using the following settings
|
||||
The Survey styling section gives you granular control over every text and input element in your survey. Expand the **Survey styling** panel to find collapsible sub-sections for Headlines & Descriptions, Inputs, Buttons, and Options.
|
||||
|
||||

|
||||
### Headlines & Descriptions
|
||||
|
||||
- **Brand Color**: Sets the primary color tone of the survey.
|
||||
- **Text Color**: This is a single color scheme that will be used across to display all the text on your survey. Ensures all text is readable against the background.
|
||||
- **Input Color:** Alters the border color of input fields.
|
||||
- **Input Border Color**: This is the color of the border of the form input field.
|
||||
Fine-tune how question headlines, descriptions, and upper labels appear:
|
||||
|
||||
2. **Card Styling:** Adjust the look of the survey card
|
||||
| Property | Description |
|
||||
|---|---|
|
||||
| **Headline Color** | Color of the question headline text |
|
||||
| **Description Color** | Color of the question description text |
|
||||
| **Headline Font Size** | Font size for headlines (in `px` or any CSS unit) |
|
||||
| **Description Font Size** | Font size for descriptions |
|
||||
| **Headline Font Weight** | Numeric font weight for headlines (e.g. `400`, `600`, `700`) |
|
||||
| **Description Font Weight** | Numeric font weight for descriptions |
|
||||
| **Upper Label Color** | Color of the small labels above input fields |
|
||||
| **Upper Label Font Size** | Font size for upper labels |
|
||||
| **Upper Label Font Weight** | Numeric font weight for upper labels |
|
||||
|
||||

|
||||
### Inputs
|
||||
|
||||
- **Roundness**: Adjusts the corner roundness of the survey card and its components (including input boxes, buttons).
|
||||
- **Card Background Color**: Sets the card's main background color.
|
||||
- **Card Border Color**: Changes the border color of the card
|
||||
Control the appearance of text inputs, textareas, and other form fields:
|
||||
|
||||
- **Hide Progress Bar**: Optionally remove the progress bar to simplify the survey experience
|
||||
- **Add Highlight Border**: Adds a distinct border for emphasis.
|
||||
| Property | Description |
|
||||
|---|---|
|
||||
| **Input Color** | Background color of input fields |
|
||||
| **Input Border Color** | Border color of input fields |
|
||||
| **Input Text Color** | Color of text typed into inputs |
|
||||
| **Border Radius** | Corner roundness of input fields (in `px` or any CSS unit) |
|
||||
| **Height** | Height of input fields |
|
||||
| **Font Size** | Font size of text inside inputs |
|
||||
| **Padding X** | Horizontal padding inside inputs |
|
||||
| **Padding Y** | Vertical padding inside inputs |
|
||||
| **Placeholder Opacity** | Opacity of placeholder text (`0` to `1`) |
|
||||
| **Shadow** | CSS box-shadow value for inputs (e.g. `0 1px 2px rgba(0,0,0,0.1)`) |
|
||||
|
||||
3. **Background Styling**: Customize the survey background with static colors, animations, or images (upload your own or get from Unsplash)
|
||||
### Buttons
|
||||
|
||||
<Note>This is only available for Link Surveys</Note>
|
||||
Customize the submit and navigation buttons:
|
||||
|
||||

|
||||
| Property | Description |
|
||||
|---|---|
|
||||
| **Button Background** | Background color of buttons |
|
||||
| **Button Text** | Text color of buttons |
|
||||
| **Border Radius** | Corner roundness of buttons |
|
||||
| **Height** | Height of buttons |
|
||||
| **Font Size** | Font size of button text |
|
||||
| **Font Weight** | Numeric font weight for button text |
|
||||
| **Padding X** | Horizontal padding inside buttons |
|
||||
| **Padding Y** | Vertical padding inside buttons |
|
||||
|
||||
- **Color**: Pick any color for the background
|
||||
- **Animation**: Add dynamic animations to enhance user experience..
|
||||
- **Upload**: Use a custom uploaded image for a personalized touch. Images must be 5 MB or less.
|
||||
- Image: Choose from Unsplash's extensive gallery. Note that these images will have a link and mention of the author & Unsplash on the bottom right to give them the credit for their awesome work!
|
||||
- **Background Overlay**: Adjust the background's opacity
|
||||
### Options
|
||||
|
||||
Style the select options in single-select, multi-select, and similar question types:
|
||||
|
||||
| Property | Description |
|
||||
|---|---|
|
||||
| **Option Background** | Background color of option items |
|
||||
| **Option Label Color** | Text color of option labels |
|
||||
| **Border Radius** | Corner roundness of option items |
|
||||
| **Padding X** | Horizontal padding inside options |
|
||||
| **Padding Y** | Vertical padding inside options |
|
||||
| **Font Size** | Font size of option text |
|
||||
|
||||
## Card Styling
|
||||
|
||||
Adjust the look of the survey card container:
|
||||
|
||||
| Property | Description |
|
||||
|---|---|
|
||||
| **Roundness** | Corner roundness of the survey card (in `px` or any CSS unit) |
|
||||
| **Card Background Color** | Background color of the survey card |
|
||||
| **Card Border Color** | Border color of the survey card |
|
||||
| **Add Highlight Border** | Adds a distinct colored border for emphasis (app surveys only) |
|
||||
| **Card Arrangement** | Layout mode for stacking cards: **Simple**, **Straight**, or **Casual** |
|
||||
|
||||
### Progress Bar
|
||||
|
||||
When the progress bar is visible (toggle **Hide Progress Bar** to control it), you can customize:
|
||||
|
||||
| Property | Description |
|
||||
|---|---|
|
||||
| **Track Background** | Background color of the progress track |
|
||||
| **Indicator Background** | Fill color of the progress indicator |
|
||||
| **Track Height** | Height of the progress bar track |
|
||||
|
||||
## Background Styling
|
||||
|
||||
Customize the survey background with static colors, animations, or images (upload your own or pick from Unsplash).
|
||||
|
||||
<Note>Background styling is only available for Link Surveys.</Note>
|
||||
|
||||
| Property | Description |
|
||||
|---|---|
|
||||
| **Color** | Pick any color for the background |
|
||||
| **Animation** | Add dynamic animations to enhance user experience |
|
||||
| **Upload** | Use a custom uploaded image (5 MB max) |
|
||||
| **Image** | Choose from Unsplash's gallery (attribution shown automatically) |
|
||||
| **Background Overlay** | Adjust the background's opacity / brightness |
|
||||
|
||||
## Add Brand Logo
|
||||
|
||||
@@ -59,30 +125,44 @@ Customize your survey with your brand's logo.
|
||||
|
||||
<Note>Brand logos are only visible on Link Survey pages.</Note>
|
||||
|
||||
1. In the Look & Feel page itself in Project settings, scroll down to see the Logo Upload box.
|
||||
<Steps>
|
||||
<Step title="Open Logo Settings">
|
||||
In the **Look & Feel** page in Project settings, scroll down to the **Logo Upload** box.
|
||||
|
||||

|
||||

|
||||
</Step>
|
||||
|
||||
2. Upload your logo. Logos must be 5 MB or less.
|
||||
<Step title="Upload Your Logo">
|
||||
Upload your logo. Logos must be 5 MB or less.
|
||||
|
||||

|
||||

|
||||
</Step>
|
||||
|
||||
3. Add a background color: If you’ve uploaded a transparent image and want to add background to it, enable this toggle and select the color of your choice.
|
||||
<Step title="Add Background Color (Optional)">
|
||||
If you've uploaded a transparent image and want to add a background to it, enable the toggle and select a color.
|
||||
|
||||

|
||||

|
||||
</Step>
|
||||
|
||||
4. Remember to save your changes!
|
||||
<Step title="Save">
|
||||
Remember to save your changes!
|
||||
|
||||

|
||||

|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Note>The logo settings apply across all Link Surveys pages.</Note>
|
||||
<Note>The logo settings apply across all Link Survey pages.</Note>
|
||||
|
||||
## Overwrite Styling Theme
|
||||
|
||||
You can allow to overwrite the styling theme for individual surveys to create unique styles for each survey:
|
||||
You can allow overwriting the styling theme for individual surveys to create unique styles per survey:
|
||||
|
||||

|
||||

|
||||
|
||||
In the survey editor, a tab called `Styling` will appear. Here you can overwrite the default styling theme.
|
||||
In the survey editor, a **Styling** tab will appear where you can overwrite the default styling theme. See the [Custom Styling](/xm-and-surveys/surveys/general-features/overwrite-styling) guide for details.
|
||||
|
||||
---
|
||||
## CSS Variables Reference
|
||||
|
||||
Under the hood, every styling property maps to a CSS variable prefixed with `--fb-`. For App & Website Surveys, you can override these directly in your global CSS file (e.g., `globals.css`) by targeting the `#fbjs` selector.
|
||||
|
||||
See the full [CSS Variables Reference](/xm-and-surveys/surveys/general-features/overwrite-styling#overwrite-css-styles-for-app--website-surveys) in the Custom Styling guide.
|
||||
|
||||
@@ -76,12 +76,4 @@ Windows XP
|
||||
Who's a Good Boy?
|
||||
"Things you've likely said to your dog."
|
||||
|
||||

|
||||
|
||||
### Fixes & Improvements:
|
||||
- **Numbered list formatting**: Fixed numbering issues.
|
||||
- **Consistent image alt text**: Updated descriptions for clarity.
|
||||
- **CSS syntax correction**: Removed unnecessary text before code block.
|
||||
- **Grammar & punctuation fixes**: Ensured clarity and smooth readability.
|
||||
|
||||
This should now display correctly on Mintlify! Let me know if you need further tweaks.
|
||||

|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
title: "Start At Specific Block"
|
||||
description:
|
||||
"Start a survey at a specific block using the URL to skip earlier blocks."
|
||||
icon: "arrow-right"
|
||||
---
|
||||
|
||||
The `startAt` URL parameter lets you open a Link Survey at a specific **block** instead of from the beginning. This is useful when you want to link to a specific part of the survey from external sources or reuse the same survey at different points in the user journey.
|
||||
|
||||
## How it works
|
||||
|
||||
The survey navigation is block-based: each block can contain one or more questions. When you pass `startAt` with a Question ID, the survey finds the **block** that contains that question and opens at that block. All questions in that block are shown together.
|
||||
|
||||
<Note>
|
||||
**Multi-question blocks:** When a block has multiple questions, `startAt` opens at the block—you will see all questions in that block, not only the question whose ID you used. For precise "start at this exact question" behavior, use one question per block.
|
||||
</Note>
|
||||
|
||||
## How to use it
|
||||
|
||||
1. In the Survey Editor, open the Questions Tab and ensure the survey is set as a **Link Survey**.
|
||||
|
||||
2. Find the question (or block) you want to start at, click on **Show Advanced Settings**, and copy the **Question ID** of any question in that block.
|
||||
|
||||
<Note>
|
||||
Each question has a unique Question ID. Since `startAt` resolves to the block containing the question, you can use any question ID from the target block—typically the first question in that block.
|
||||
</Note>
|
||||
|
||||
3. Append `?startAt=question_id` to your survey's URL, replacing `question_id` with the copied Question ID.
|
||||
|
||||
4. Share this modified URL with your users to start the survey at the specified block.
|
||||
|
||||
### Sample Link Survey URL with `startAt`
|
||||
|
||||
```sh Example Link Survey URL with startAt configured
|
||||
https://formbricks.com/clny997dj087ho30fdzyf4nkl?startAt=bqd29m94l9k0hnc3azbrexl8
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
- **Link to a specific block from an external source:** Direct users to a specific block in your survey from emails, chatbots, or web pages.
|
||||
- **Use the same survey in different parts of the user journey:** Reuse the survey at different stages, starting at different blocks to gather insights.
|
||||
- **Create a personalized survey experience:** Tailor the survey by starting at a particular block based on the user's past interactions or preferences.
|
||||
@@ -1,36 +0,0 @@
|
||||
---
|
||||
title: "Start At Specific Question"
|
||||
description:
|
||||
"Start a survey at a specific question using the URL to skip the initial questions."
|
||||
icon: "arrow-right"
|
||||
---
|
||||
|
||||
You can start a survey at a specific question from the survey using the URL to skip the initial questions. This is useful when you want to link to a specific question from an external source or want to use the same survey in different parts of the user journey.
|
||||
|
||||
## How to Use it?
|
||||
|
||||
1. In the Survey Editor, open the Questions Tab and ensure the survey is set as a **Link Survey**.
|
||||
|
||||
2. Find the question you want to start at, click on **Show Advanced Settings**, and copy the **Question ID**.
|
||||
|
||||
<Note>
|
||||
Each question has a unique Question ID, which is used to identify it in the
|
||||
survey. You can use different Question IDs for multiple **startAt** points in
|
||||
the URL.
|
||||
</Note>
|
||||
|
||||
3. Append `?startAt=question_id` to your survey's URL, replacing `question_id` with the copied Question ID.
|
||||
|
||||
4. Share this modified URL with your users to start the survey at the specified question.
|
||||
|
||||
### Sample Link Survey URL with `startAt`
|
||||
|
||||
```sh Example Link Survey URL with startAt configured
|
||||
https://formbricks.com/clny997dj087ho30fdzyf4nkl?startAt=bqd29m94l9k0hnc3azbrexl8
|
||||
```
|
||||
|
||||
## Use Cases
|
||||
|
||||
- **Link to a specific question from an external source:** Use this feature to direct users to a specific question in your survey from emails, chatbots, or web pages, providing a seamless experience.
|
||||
- **Use the same survey in different parts of the user journey:** Employ the same survey at various stages of the user journey, starting at different questions to gather comprehensive insights.
|
||||
- **Create a personalized survey experience:** Tailor the survey experience by starting at a particular question based on the user's past interactions or preferences, enhancing engagement.
|
||||
Vendored
+1
-1
@@ -39,7 +39,7 @@
|
||||
"dependencies": {
|
||||
"@formbricks/logger": "workspace:*",
|
||||
"redis": "5.8.1",
|
||||
"zod": "3.24.4"
|
||||
"zod": "3.25.76"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@formbricks/config-typescript": "workspace:*",
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
"@prisma/client": "6.14.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
"uuid": "11.1.0",
|
||||
"zod": "3.24.4",
|
||||
"zod": "3.25.76",
|
||||
"zod-openapi": "4.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"@formbricks/config-typescript": "workspace:*",
|
||||
"@formbricks/eslint-config": "workspace:*",
|
||||
"@formbricks/types": "workspace:*",
|
||||
"@react-email/preview-server": "5.2.5",
|
||||
"@react-email/preview-server": "5.2.8",
|
||||
"autoprefixer": "10.4.21",
|
||||
"clsx": "2.1.1",
|
||||
"postcss": "8.5.3",
|
||||
|
||||
@@ -887,6 +887,7 @@ describe("utils.ts", () => {
|
||||
targetElement.className = "other";
|
||||
|
||||
targetElement.matches = vi.fn(() => false);
|
||||
targetElement.closest = vi.fn(() => null); // no ancestor matches either
|
||||
|
||||
const action: TEnvironmentStateActionClass = {
|
||||
id: "clabc123abc",
|
||||
@@ -993,13 +994,93 @@ describe("utils.ts", () => {
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
// --- Regression tests for nested child click target (issue #7314) ---
|
||||
// In this test environment document.createElement() returns a plain mock object,
|
||||
// so we set .matches and .closest as vi.fn() — the same pattern used by existing tests.
|
||||
// This exercises the exact code path of the fix: matches() fails → closest() succeeds.
|
||||
|
||||
test("returns true when clicking a child element inside a button matched by cssSelector", () => {
|
||||
const button = document.createElement("button");
|
||||
const icon = document.createElement("span");
|
||||
|
||||
// Simulate: icon does NOT directly match ".my-btn", but its closest ancestor does
|
||||
(icon as unknown as { matches: ReturnType<typeof vi.fn> }).matches = vi.fn(() => false);
|
||||
(icon as unknown as { closest: ReturnType<typeof vi.fn> }).closest = vi.fn(() => button);
|
||||
|
||||
const action: TEnvironmentStateActionClass = {
|
||||
id: "clabc123abc",
|
||||
name: "Test Action",
|
||||
type: "noCode",
|
||||
key: null,
|
||||
noCodeConfig: {
|
||||
type: "click",
|
||||
urlFilters: [],
|
||||
elementSelector: { cssSelector: ".my-btn" },
|
||||
},
|
||||
};
|
||||
|
||||
// Before fix: matches() → false → returns false (bug)
|
||||
// After fix: matches() → false → closest() → button → returns true (correct)
|
||||
const result = evaluateNoCodeConfigClick(icon as unknown as HTMLElement, action);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
test("returns false when clicking a child element with no matching ancestor", () => {
|
||||
const other = document.createElement("div");
|
||||
|
||||
// Simulate: element doesn't match, and no ancestor matches either
|
||||
(other as unknown as { matches: ReturnType<typeof vi.fn> }).matches = vi.fn(() => false);
|
||||
(other as unknown as { closest: ReturnType<typeof vi.fn> }).closest = vi.fn(() => null);
|
||||
|
||||
const action: TEnvironmentStateActionClass = {
|
||||
id: "clabc123abc",
|
||||
name: "Test Action",
|
||||
type: "noCode",
|
||||
key: null,
|
||||
noCodeConfig: {
|
||||
type: "click",
|
||||
urlFilters: [],
|
||||
elementSelector: { cssSelector: ".my-btn" },
|
||||
},
|
||||
};
|
||||
|
||||
const result = evaluateNoCodeConfigClick(other as unknown as HTMLElement, action);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
test("uses direct target (not closest) when target directly matches cssSelector", () => {
|
||||
const button = document.createElement("button");
|
||||
|
||||
// Simulate: click on the button itself — matches() succeeds, closest() should NOT be called
|
||||
(button as unknown as { matches: ReturnType<typeof vi.fn> }).matches = vi.fn(() => true);
|
||||
const closestSpy = vi.fn();
|
||||
(button as unknown as { closest: ReturnType<typeof vi.fn> }).closest = closestSpy;
|
||||
|
||||
const action: TEnvironmentStateActionClass = {
|
||||
id: "clabc123abc",
|
||||
name: "Test Action",
|
||||
type: "noCode",
|
||||
key: null,
|
||||
noCodeConfig: {
|
||||
type: "click",
|
||||
urlFilters: [],
|
||||
elementSelector: { cssSelector: ".my-btn" },
|
||||
},
|
||||
};
|
||||
|
||||
const result = evaluateNoCodeConfigClick(button as unknown as HTMLElement, action);
|
||||
expect(result).toBe(true);
|
||||
expect(closestSpy).not.toHaveBeenCalled(); // closest() is only a fallback
|
||||
});
|
||||
|
||||
test("handles multiple cssSelectors correctly", () => {
|
||||
const targetElement = document.createElement("div");
|
||||
targetElement.className = "test other";
|
||||
|
||||
targetElement.matches = vi.fn((selector) => {
|
||||
return selector === ".test" || selector === ".other";
|
||||
return selector === ".test" || selector === ".other" || selector === ".test .other";
|
||||
});
|
||||
targetElement.closest = vi.fn(() => null); // not needed but consistent with mock environment
|
||||
|
||||
const action: TEnvironmentStateActionClass = {
|
||||
id: "clabc123abc",
|
||||
|
||||
@@ -304,20 +304,28 @@ export const evaluateNoCodeConfigClick = (
|
||||
|
||||
if (!innerHtml && !cssSelector) return false;
|
||||
|
||||
if (innerHtml && targetElement.innerHTML !== innerHtml) return false;
|
||||
// Resolve the element to test: prefer the direct click target, but walk up to
|
||||
// the nearest ancestor that matches the CSS selector (event delegation for nested markup,
|
||||
// e.g. <svg> or <span> inside a <button class="my-btn">).
|
||||
let matchedElement: HTMLElement = targetElement;
|
||||
|
||||
if (cssSelector) {
|
||||
// Split selectors that start with a . or # including the . or #
|
||||
const individualSelectors = cssSelector
|
||||
.split(/(?=[.#])/) // split before each . or #
|
||||
.map((sel) => sel.trim()); // remove leftover whitespace
|
||||
for (const selector of individualSelectors) {
|
||||
if (!targetElement.matches(selector)) {
|
||||
return false;
|
||||
}
|
||||
let matchesDirectly = false;
|
||||
try {
|
||||
matchesDirectly = targetElement.matches(cssSelector);
|
||||
} catch {
|
||||
matchesDirectly = false;
|
||||
}
|
||||
if (!matchesDirectly) {
|
||||
const ancestor = targetElement.closest(cssSelector);
|
||||
if (!ancestor) return false;
|
||||
matchedElement = ancestor as HTMLElement;
|
||||
}
|
||||
}
|
||||
|
||||
// Check innerHtml against the resolved element, not the raw click target
|
||||
if (innerHtml && matchedElement.innerHTML !== innerHtml) return false;
|
||||
|
||||
const connector = action.noCodeConfig.urlFiltersConnector ?? "or";
|
||||
const isValidUrl = handleUrlFilters(urlFilters, connector);
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
},
|
||||
"author": "Formbricks <hola@formbricks.com>",
|
||||
"dependencies": {
|
||||
"zod": "3.24.4",
|
||||
"zod": "3.25.76",
|
||||
"pino": "10.0.0",
|
||||
"pino-opentelemetry-transport": "2.0.0",
|
||||
"pino-pretty": "13.1.1"
|
||||
|
||||
@@ -80,7 +80,7 @@ describe("service.ts", () => {
|
||||
Key: "uploads/images/test-file.jpg",
|
||||
Fields: {
|
||||
"Content-Type": "image/jpeg",
|
||||
// "Content-Encoding": "base64",
|
||||
success_action_status: "201",
|
||||
},
|
||||
Conditions: [["content-length-range", 0, mockMaxSize]],
|
||||
});
|
||||
@@ -175,7 +175,7 @@ describe("service.ts", () => {
|
||||
Key: "uploads/images/test-file.jpg",
|
||||
Fields: {
|
||||
"Content-Type": "image/jpeg",
|
||||
// "Content-Encoding": "base64",
|
||||
success_action_status: "201",
|
||||
},
|
||||
Conditions: [["content-length-range", 0, mockMaxSize]],
|
||||
});
|
||||
|
||||
@@ -66,7 +66,7 @@ export const getSignedUploadUrl = async (
|
||||
Key: `${filePath}/${fileName}`,
|
||||
Fields: {
|
||||
"Content-Type": contentType,
|
||||
// "Content-Encoding": "base64",
|
||||
success_action_status: "201",
|
||||
},
|
||||
Conditions: postConditions,
|
||||
});
|
||||
|
||||
@@ -57,6 +57,36 @@
|
||||
color: var(--fb-subheading-color) !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore list styling for rich text (questions/descriptions).
|
||||
* Preflight resets ul/ol with list-style:none; these overrides restore bullets/numbers.
|
||||
*/
|
||||
#fbjs .htmlbody ul,
|
||||
#fbjs .htmlbody ol,
|
||||
#fbjs [data-variant="headline"] ul,
|
||||
#fbjs [data-variant="headline"] ol,
|
||||
#fbjs [data-variant="description"] ul,
|
||||
#fbjs [data-variant="description"] ol {
|
||||
list-style-position: outside;
|
||||
margin: 0.5em 0;
|
||||
padding-left: 1.5em;
|
||||
}
|
||||
#fbjs .htmlbody ul,
|
||||
#fbjs [data-variant="headline"] ul,
|
||||
#fbjs [data-variant="description"] ul {
|
||||
list-style-type: disc;
|
||||
}
|
||||
#fbjs .htmlbody ol,
|
||||
#fbjs [data-variant="headline"] ol,
|
||||
#fbjs [data-variant="description"] ol {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
#fbjs .htmlbody li,
|
||||
#fbjs [data-variant="headline"] li,
|
||||
#fbjs [data-variant="description"] li {
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
|
||||
/* without this, it wont override the color */
|
||||
#fbjs p.editor-paragraph {
|
||||
overflow-wrap: break-word;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "6.14.0",
|
||||
"zod": "3.24.4",
|
||||
"zod": "3.25.76",
|
||||
"zod-openapi": "4.2.4",
|
||||
"node-html-parser": "7.0.1"
|
||||
},
|
||||
|
||||
Generated
+302
-160
@@ -297,7 +297,7 @@ importers:
|
||||
version: 10.5.0(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(webpack@5.99.8(esbuild@0.25.12))
|
||||
'@t3-oss/env-nextjs':
|
||||
specifier: 0.13.4
|
||||
version: 0.13.4(arktype@2.1.29)(typescript@5.8.3)(zod@3.24.4)
|
||||
version: 0.13.4(arktype@2.1.29)(typescript@5.8.3)(zod@3.25.76)
|
||||
'@tailwindcss/forms':
|
||||
specifier: 0.5.10
|
||||
version: 0.5.10(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@22.15.18)(typescript@5.8.3)))
|
||||
@@ -390,7 +390,7 @@ importers:
|
||||
version: 4.24.12(patch_hash=7ac5717a8d7d2049442182b5d83ab492d33fe774ff51ff5ea3884628b77df87b)(next@16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(nodemailer@7.0.11)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
next-safe-action:
|
||||
specifier: 7.10.8
|
||||
version: 7.10.8(next@16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.24.4)
|
||||
version: 7.10.8(next@16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76)
|
||||
node-fetch:
|
||||
specifier: 3.3.2
|
||||
version: 3.3.2
|
||||
@@ -482,11 +482,11 @@ importers:
|
||||
specifier: file:vendor/xlsx-0.20.3.tgz
|
||||
version: file:apps/web/vendor/xlsx-0.20.3.tgz
|
||||
zod:
|
||||
specifier: 3.24.4
|
||||
version: 3.24.4
|
||||
specifier: 3.25.76
|
||||
version: 3.25.76
|
||||
zod-openapi:
|
||||
specifier: 4.2.4
|
||||
version: 4.2.4(zod@3.24.4)
|
||||
version: 4.2.4(zod@3.25.76)
|
||||
devDependencies:
|
||||
'@formbricks/config-typescript':
|
||||
specifier: workspace:*
|
||||
@@ -582,8 +582,8 @@ importers:
|
||||
specifier: 5.8.1
|
||||
version: 5.8.1
|
||||
zod:
|
||||
specifier: 3.24.4
|
||||
version: 3.24.4
|
||||
specifier: 3.25.76
|
||||
version: 3.25.76
|
||||
devDependencies:
|
||||
'@formbricks/config-typescript':
|
||||
specifier: workspace:*
|
||||
@@ -685,11 +685,11 @@ importers:
|
||||
specifier: 11.1.0
|
||||
version: 11.1.0
|
||||
zod:
|
||||
specifier: 3.24.4
|
||||
version: 3.24.4
|
||||
specifier: 3.25.76
|
||||
version: 3.25.76
|
||||
zod-openapi:
|
||||
specifier: 4.2.4
|
||||
version: 4.2.4(zod@3.24.4)
|
||||
version: 4.2.4(zod@3.25.76)
|
||||
devDependencies:
|
||||
'@formbricks/config-typescript':
|
||||
specifier: workspace:*
|
||||
@@ -744,8 +744,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../types
|
||||
'@react-email/preview-server':
|
||||
specifier: 5.2.5
|
||||
version: 5.2.5(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
specifier: 5.2.8
|
||||
version: 5.2.8(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
autoprefixer:
|
||||
specifier: 10.4.21
|
||||
version: 10.4.21(postcss@8.5.3)
|
||||
@@ -829,8 +829,8 @@ importers:
|
||||
specifier: 13.1.1
|
||||
version: 13.1.1
|
||||
zod:
|
||||
specifier: 3.24.4
|
||||
version: 3.24.4
|
||||
specifier: 3.25.76
|
||||
version: 3.25.76
|
||||
devDependencies:
|
||||
'@formbricks/config-typescript':
|
||||
specifier: workspace:*
|
||||
@@ -1067,11 +1067,11 @@ importers:
|
||||
specifier: 7.0.1
|
||||
version: 7.0.1
|
||||
zod:
|
||||
specifier: 3.24.4
|
||||
version: 3.24.4
|
||||
specifier: 3.25.76
|
||||
version: 3.25.76
|
||||
zod-openapi:
|
||||
specifier: 4.2.4
|
||||
version: 4.2.4(zod@3.24.4)
|
||||
version: 4.2.4(zod@3.25.76)
|
||||
devDependencies:
|
||||
'@formbricks/config-typescript':
|
||||
specifier: workspace:*
|
||||
@@ -1827,6 +1827,12 @@ packages:
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/aix-ppc64@0.25.10':
|
||||
resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/aix-ppc64@0.25.12':
|
||||
resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -1845,6 +1851,12 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm64@0.25.12':
|
||||
resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -1863,6 +1875,12 @@ packages:
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.25.10':
|
||||
resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.25.12':
|
||||
resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -1881,6 +1899,12 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.25.10':
|
||||
resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.25.12':
|
||||
resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -1899,6 +1923,12 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-arm64@0.25.12':
|
||||
resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -1917,6 +1947,12 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.25.10':
|
||||
resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.25.12':
|
||||
resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -1935,6 +1971,12 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.25.12':
|
||||
resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -1953,6 +1995,12 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.25.10':
|
||||
resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.25.12':
|
||||
resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -1971,6 +2019,12 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm64@0.25.12':
|
||||
resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -1989,6 +2043,12 @@ packages:
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.25.10':
|
||||
resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.25.12':
|
||||
resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2007,6 +2067,12 @@ packages:
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.25.10':
|
||||
resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.25.12':
|
||||
resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2025,6 +2091,12 @@ packages:
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.25.10':
|
||||
resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.25.12':
|
||||
resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2043,6 +2115,12 @@ packages:
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.25.10':
|
||||
resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.25.12':
|
||||
resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2061,6 +2139,12 @@ packages:
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.25.10':
|
||||
resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.25.12':
|
||||
resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2079,6 +2163,12 @@ packages:
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.25.10':
|
||||
resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.25.12':
|
||||
resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2097,6 +2187,12 @@ packages:
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.25.10':
|
||||
resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.25.12':
|
||||
resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2115,6 +2211,12 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.25.10':
|
||||
resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.25.12':
|
||||
resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2127,6 +2229,12 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/netbsd-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-arm64@0.25.12':
|
||||
resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2145,6 +2253,12 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.25.10':
|
||||
resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.25.12':
|
||||
resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2163,6 +2277,12 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-arm64@0.25.12':
|
||||
resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2181,6 +2301,12 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.25.10':
|
||||
resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.25.12':
|
||||
resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2193,6 +2319,12 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openharmony-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@esbuild/openharmony-arm64@0.25.12':
|
||||
resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2211,6 +2343,12 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/sunos-x64@0.25.10':
|
||||
resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/sunos-x64@0.25.12':
|
||||
resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2229,6 +2367,12 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-arm64@0.25.12':
|
||||
resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2247,6 +2391,12 @@ packages:
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.25.10':
|
||||
resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.25.12':
|
||||
resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2265,6 +2415,12 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.25.10':
|
||||
resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.25.12':
|
||||
resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2845,46 +3001,24 @@ packages:
|
||||
'@neoconfetti/react@1.0.0':
|
||||
resolution: {integrity: sha512-klcSooChXXOzIm+SE5IISIAn3bYzYfPjbX7D7HoqZL84oAfgREeSg5vSIaSFH+DaGzzvImTyWe1OyrJ67vik4A==}
|
||||
|
||||
'@next/env@16.0.10':
|
||||
resolution: {integrity: sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang==}
|
||||
|
||||
'@next/env@16.1.6':
|
||||
resolution: {integrity: sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==}
|
||||
|
||||
'@next/eslint-plugin-next@15.3.2':
|
||||
resolution: {integrity: sha512-ijVRTXBgnHT33aWnDtmlG+LJD+5vhc9AKTJPquGG5NKXjpKNjc62woIhFtrAcWdBobt8kqjCoaJ0q6sDQoX7aQ==}
|
||||
|
||||
'@next/swc-darwin-arm64@16.0.10':
|
||||
resolution: {integrity: sha512-4XgdKtdVsaflErz+B5XeG0T5PeXKDdruDf3CRpnhN+8UebNa5N2H58+3GDgpn/9GBurrQ1uWW768FfscwYkJRg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@next/swc-darwin-arm64@16.1.6':
|
||||
resolution: {integrity: sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@next/swc-darwin-x64@16.0.10':
|
||||
resolution: {integrity: sha512-spbEObMvRKkQ3CkYVOME+ocPDFo5UqHb8EMTS78/0mQ+O1nqE8toHJVioZo4TvebATxgA8XMTHHrScPrn68OGw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@next/swc-darwin-x64@16.1.6':
|
||||
resolution: {integrity: sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@next/swc-linux-arm64-gnu@16.0.10':
|
||||
resolution: {integrity: sha512-uQtWE3X0iGB8apTIskOMi2w/MKONrPOUCi5yLO+v3O8Mb5c7K4Q5KD1jvTpTF5gJKa3VH/ijKjKUq9O9UhwOYw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@next/swc-linux-arm64-gnu@16.1.6':
|
||||
resolution: {integrity: sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==}
|
||||
engines: {node: '>= 10'}
|
||||
@@ -2892,13 +3026,6 @@ packages:
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@next/swc-linux-arm64-musl@16.0.10':
|
||||
resolution: {integrity: sha512-llA+hiDTrYvyWI21Z0L1GiXwjQaanPVQQwru5peOgtooeJ8qx3tlqRV2P7uH2pKQaUfHxI/WVarvI5oYgGxaTw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@next/swc-linux-arm64-musl@16.1.6':
|
||||
resolution: {integrity: sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==}
|
||||
engines: {node: '>= 10'}
|
||||
@@ -2906,13 +3033,6 @@ packages:
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@next/swc-linux-x64-gnu@16.0.10':
|
||||
resolution: {integrity: sha512-AK2q5H0+a9nsXbeZ3FZdMtbtu9jxW4R/NgzZ6+lrTm3d6Zb7jYrWcgjcpM1k8uuqlSy4xIyPR2YiuUr+wXsavA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@next/swc-linux-x64-gnu@16.1.6':
|
||||
resolution: {integrity: sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==}
|
||||
engines: {node: '>= 10'}
|
||||
@@ -2920,13 +3040,6 @@ packages:
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@next/swc-linux-x64-musl@16.0.10':
|
||||
resolution: {integrity: sha512-1TDG9PDKivNw5550S111gsO4RGennLVl9cipPhtkXIFVwo31YZ73nEbLjNC8qG3SgTz/QZyYyaFYMeY4BKZR/g==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@next/swc-linux-x64-musl@16.1.6':
|
||||
resolution: {integrity: sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==}
|
||||
engines: {node: '>= 10'}
|
||||
@@ -2934,24 +3047,12 @@ packages:
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@next/swc-win32-arm64-msvc@16.0.10':
|
||||
resolution: {integrity: sha512-aEZIS4Hh32xdJQbHz121pyuVZniSNoqDVx1yIr2hy+ZwJGipeqnMZBJHyMxv2tiuAXGx6/xpTcQJ6btIiBjgmg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@next/swc-win32-arm64-msvc@16.1.6':
|
||||
resolution: {integrity: sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@next/swc-win32-x64-msvc@16.0.10':
|
||||
resolution: {integrity: sha512-E+njfCoFLb01RAFEnGZn6ERoOqhK1Gl3Lfz1Kjnj0Ulfu7oJbuMyvBKNj/bw8XZnenHDASlygTjZICQW+rYW1Q==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@next/swc-win32-x64-msvc@16.1.6':
|
||||
resolution: {integrity: sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==}
|
||||
engines: {node: '>= 10'}
|
||||
@@ -4521,8 +4622,8 @@ packages:
|
||||
peerDependencies:
|
||||
react: ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
|
||||
'@react-email/preview-server@5.2.5':
|
||||
resolution: {integrity: sha512-YERhEKl0Dz2qNbHTzdSwnsK15gipEqonKMPEbsoE8C+ACiHIm/f/d1UzQVmhrsN6PW7L+JhAuzcdIX1H3pLmFg==}
|
||||
'@react-email/preview-server@5.2.8':
|
||||
resolution: {integrity: sha512-drQ0C7vi7P0uE7Ox1Cyiujsx0oqp2RbIscOdSBR5qvzw3EKjlGbW2pWjQ000cjxTq3Si7lqlRKhOIF8MzOnqHw==}
|
||||
|
||||
'@react-email/preview@0.0.14':
|
||||
resolution: {integrity: sha512-aYK8q0IPkBXyMsbpMXgxazwHxYJxTrXrV95GFuu2HbEiIToMwSyUgb8HDFYwPqqfV03/jbwqlsXmFxsOd+VNaw==}
|
||||
@@ -7602,6 +7703,11 @@ packages:
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
esbuild@0.25.10:
|
||||
resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
esbuild@0.25.12:
|
||||
resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -9326,27 +9432,6 @@ packages:
|
||||
zod:
|
||||
optional: true
|
||||
|
||||
next@16.0.10:
|
||||
resolution: {integrity: sha512-RtWh5PUgI+vxlV3HdR+IfWA1UUHu0+Ram/JBO4vWB54cVPentCD0e+lxyAYEsDTqGGMg7qpjhKh6dc6aW7W/sA==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@opentelemetry/api': ^1.1.0
|
||||
'@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
|
||||
sass: ^1.3.0
|
||||
peerDependenciesMeta:
|
||||
'@opentelemetry/api':
|
||||
optional: true
|
||||
'@playwright/test':
|
||||
optional: true
|
||||
babel-plugin-react-compiler:
|
||||
optional: true
|
||||
sass:
|
||||
optional: true
|
||||
|
||||
next@16.1.6:
|
||||
resolution: {integrity: sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
@@ -11758,8 +11843,8 @@ packages:
|
||||
peerDependencies:
|
||||
zod: ^3.21.4
|
||||
|
||||
zod@3.24.4:
|
||||
resolution: {integrity: sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==}
|
||||
zod@3.25.76:
|
||||
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
|
||||
|
||||
snapshots:
|
||||
|
||||
@@ -13575,6 +13660,9 @@ snapshots:
|
||||
'@esbuild/aix-ppc64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/aix-ppc64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/aix-ppc64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13584,6 +13672,9 @@ snapshots:
|
||||
'@esbuild/android-arm64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13593,6 +13684,9 @@ snapshots:
|
||||
'@esbuild/android-arm@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13602,6 +13696,9 @@ snapshots:
|
||||
'@esbuild/android-x64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13611,6 +13708,9 @@ snapshots:
|
||||
'@esbuild/darwin-arm64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13620,6 +13720,9 @@ snapshots:
|
||||
'@esbuild/darwin-x64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13629,6 +13732,9 @@ snapshots:
|
||||
'@esbuild/freebsd-arm64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13638,6 +13744,9 @@ snapshots:
|
||||
'@esbuild/freebsd-x64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13647,6 +13756,9 @@ snapshots:
|
||||
'@esbuild/linux-arm64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13656,6 +13768,9 @@ snapshots:
|
||||
'@esbuild/linux-arm@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13665,6 +13780,9 @@ snapshots:
|
||||
'@esbuild/linux-ia32@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13674,6 +13792,9 @@ snapshots:
|
||||
'@esbuild/linux-loong64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13683,6 +13804,9 @@ snapshots:
|
||||
'@esbuild/linux-mips64el@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13692,6 +13816,9 @@ snapshots:
|
||||
'@esbuild/linux-ppc64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13701,6 +13828,9 @@ snapshots:
|
||||
'@esbuild/linux-riscv64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13710,6 +13840,9 @@ snapshots:
|
||||
'@esbuild/linux-s390x@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13719,12 +13852,18 @@ snapshots:
|
||||
'@esbuild/linux-x64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.25.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-arm64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13734,6 +13873,9 @@ snapshots:
|
||||
'@esbuild/netbsd-x64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13743,6 +13885,9 @@ snapshots:
|
||||
'@esbuild/openbsd-arm64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-arm64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13752,12 +13897,18 @@ snapshots:
|
||||
'@esbuild/openbsd-x64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.25.12':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openharmony-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openharmony-arm64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13767,6 +13918,9 @@ snapshots:
|
||||
'@esbuild/sunos-x64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13776,6 +13930,9 @@ snapshots:
|
||||
'@esbuild/win32-arm64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13785,6 +13942,9 @@ snapshots:
|
||||
'@esbuild/win32-ia32@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -13794,6 +13954,9 @@ snapshots:
|
||||
'@esbuild/win32-x64@0.23.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.25.12':
|
||||
optional: true
|
||||
|
||||
@@ -14441,59 +14604,33 @@ snapshots:
|
||||
|
||||
'@neoconfetti/react@1.0.0': {}
|
||||
|
||||
'@next/env@16.0.10': {}
|
||||
|
||||
'@next/env@16.1.6': {}
|
||||
|
||||
'@next/eslint-plugin-next@15.3.2':
|
||||
dependencies:
|
||||
fast-glob: 3.3.1
|
||||
|
||||
'@next/swc-darwin-arm64@16.0.10':
|
||||
optional: true
|
||||
|
||||
'@next/swc-darwin-arm64@16.1.6':
|
||||
optional: true
|
||||
|
||||
'@next/swc-darwin-x64@16.0.10':
|
||||
optional: true
|
||||
|
||||
'@next/swc-darwin-x64@16.1.6':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-gnu@16.0.10':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-gnu@16.1.6':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-musl@16.0.10':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-musl@16.1.6':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-gnu@16.0.10':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-gnu@16.1.6':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-musl@16.0.10':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-musl@16.1.6':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-arm64-msvc@16.0.10':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-arm64-msvc@16.1.6':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-x64-msvc@16.0.10':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-x64-msvc@16.1.6':
|
||||
optional: true
|
||||
|
||||
@@ -16719,9 +16856,10 @@ snapshots:
|
||||
marked: 15.0.12
|
||||
react: 19.2.3
|
||||
|
||||
'@react-email/preview-server@5.2.5(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
|
||||
'@react-email/preview-server@5.2.8(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
|
||||
dependencies:
|
||||
next: 16.0.10(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
esbuild: 0.25.10
|
||||
next: 16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- '@opentelemetry/api'
|
||||
@@ -17928,19 +18066,19 @@ snapshots:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@t3-oss/env-core@0.13.4(arktype@2.1.29)(typescript@5.8.3)(zod@3.24.4)':
|
||||
'@t3-oss/env-core@0.13.4(arktype@2.1.29)(typescript@5.8.3)(zod@3.25.76)':
|
||||
dependencies:
|
||||
arktype: 2.1.29
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
zod: 3.24.4
|
||||
zod: 3.25.76
|
||||
|
||||
'@t3-oss/env-nextjs@0.13.4(arktype@2.1.29)(typescript@5.8.3)(zod@3.24.4)':
|
||||
'@t3-oss/env-nextjs@0.13.4(arktype@2.1.29)(typescript@5.8.3)(zod@3.25.76)':
|
||||
dependencies:
|
||||
'@t3-oss/env-core': 0.13.4(arktype@2.1.29)(typescript@5.8.3)(zod@3.24.4)
|
||||
'@t3-oss/env-core': 0.13.4(arktype@2.1.29)(typescript@5.8.3)(zod@3.25.76)
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
zod: 3.24.4
|
||||
zod: 3.25.76
|
||||
transitivePeerDependencies:
|
||||
- arktype
|
||||
|
||||
@@ -20291,6 +20429,35 @@ snapshots:
|
||||
'@esbuild/win32-ia32': 0.23.1
|
||||
'@esbuild/win32-x64': 0.23.1
|
||||
|
||||
esbuild@0.25.10:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.25.10
|
||||
'@esbuild/android-arm': 0.25.10
|
||||
'@esbuild/android-arm64': 0.25.10
|
||||
'@esbuild/android-x64': 0.25.10
|
||||
'@esbuild/darwin-arm64': 0.25.10
|
||||
'@esbuild/darwin-x64': 0.25.10
|
||||
'@esbuild/freebsd-arm64': 0.25.10
|
||||
'@esbuild/freebsd-x64': 0.25.10
|
||||
'@esbuild/linux-arm': 0.25.10
|
||||
'@esbuild/linux-arm64': 0.25.10
|
||||
'@esbuild/linux-ia32': 0.25.10
|
||||
'@esbuild/linux-loong64': 0.25.10
|
||||
'@esbuild/linux-mips64el': 0.25.10
|
||||
'@esbuild/linux-ppc64': 0.25.10
|
||||
'@esbuild/linux-riscv64': 0.25.10
|
||||
'@esbuild/linux-s390x': 0.25.10
|
||||
'@esbuild/linux-x64': 0.25.10
|
||||
'@esbuild/netbsd-arm64': 0.25.10
|
||||
'@esbuild/netbsd-x64': 0.25.10
|
||||
'@esbuild/openbsd-arm64': 0.25.10
|
||||
'@esbuild/openbsd-x64': 0.25.10
|
||||
'@esbuild/openharmony-arm64': 0.25.10
|
||||
'@esbuild/sunos-x64': 0.25.10
|
||||
'@esbuild/win32-arm64': 0.25.10
|
||||
'@esbuild/win32-ia32': 0.25.10
|
||||
'@esbuild/win32-x64': 0.25.10
|
||||
|
||||
esbuild@0.25.12:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.25.12
|
||||
@@ -22203,38 +22370,13 @@ snapshots:
|
||||
optionalDependencies:
|
||||
nodemailer: 7.0.11
|
||||
|
||||
next-safe-action@7.10.8(next@16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.24.4):
|
||||
next-safe-action@7.10.8(next@16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76):
|
||||
dependencies:
|
||||
next: 16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
react: 19.2.3
|
||||
react-dom: 19.2.3(react@19.2.3)
|
||||
optionalDependencies:
|
||||
zod: 3.24.4
|
||||
|
||||
next@16.0.10(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
||||
dependencies:
|
||||
'@next/env': 16.0.10
|
||||
'@swc/helpers': 0.5.15
|
||||
caniuse-lite: 1.0.30001762
|
||||
postcss: 8.4.31
|
||||
react: 19.2.3
|
||||
react-dom: 19.2.3(react@19.2.3)
|
||||
styled-jsx: 5.1.6(@babel/core@7.28.5)(react@19.2.3)
|
||||
optionalDependencies:
|
||||
'@next/swc-darwin-arm64': 16.0.10
|
||||
'@next/swc-darwin-x64': 16.0.10
|
||||
'@next/swc-linux-arm64-gnu': 16.0.10
|
||||
'@next/swc-linux-arm64-musl': 16.0.10
|
||||
'@next/swc-linux-x64-gnu': 16.0.10
|
||||
'@next/swc-linux-x64-musl': 16.0.10
|
||||
'@next/swc-win32-arm64-msvc': 16.0.10
|
||||
'@next/swc-win32-x64-msvc': 16.0.10
|
||||
'@opentelemetry/api': 1.9.0
|
||||
'@playwright/test': 1.56.1
|
||||
sharp: 0.34.5
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- babel-plugin-macros
|
||||
zod: 3.25.76
|
||||
|
||||
next@16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
||||
dependencies:
|
||||
@@ -25089,8 +25231,8 @@ snapshots:
|
||||
|
||||
yoga-layout@3.2.1: {}
|
||||
|
||||
zod-openapi@4.2.4(zod@3.24.4):
|
||||
zod-openapi@4.2.4(zod@3.25.76):
|
||||
dependencies:
|
||||
zod: 3.24.4
|
||||
zod: 3.25.76
|
||||
|
||||
zod@3.24.4: {}
|
||||
zod@3.25.76: {}
|
||||
|
||||
Reference in New Issue
Block a user