diff --git a/apps/docs/content/docs/developers/api/teams.mdx b/apps/docs/content/docs/developers/api/teams.mdx index 99d708b41..0d869c56c 100644 --- a/apps/docs/content/docs/developers/api/teams.mdx +++ b/apps/docs/content/docs/developers/api/teams.mdx @@ -95,7 +95,7 @@ Documents created with a team token belong to that team: ```bash curl -X POST "https://app.documenso.com/api/v2/envelope/create" \ - -H "Authorization: api_team_xxxxxxxxxxxxxxxx" \ + -H "Authorization: api_xxxxxxxxxxxxxxxx" \ -H "Content-Type: multipart/form-data" \ -F 'payload={ "type": "DOCUMENT", @@ -157,11 +157,11 @@ Retrieve all documents belonging to the team: ```bash # List all team documents curl -X GET "https://app.documenso.com/api/v2/envelope" \ - -H "Authorization: api_team_xxxxxxxxxxxxxxxx" + -H "Authorization: api_xxxxxxxxxxxxxxxx" # Filter by status curl -X GET "https://app.documenso.com/api/v2/envelope?status=PENDING" \ - -H "Authorization: api_team_xxxxxxxxxxxxxxxx" + -H "Authorization: api_xxxxxxxxxxxxxxxx" ```` @@ -191,7 +191,7 @@ Templates created with a team token are shared across the team. ```bash curl -X POST "https://app.documenso.com/api/v2/template/create" \ - -H "Authorization: api_team_xxxxxxxxxxxxxxxx" \ + -H "Authorization: api_xxxxxxxxxxxxxxxx" \ -H "Content-Type: multipart/form-data" \ -F 'payload={ "title": "NDA Template", @@ -269,7 +269,7 @@ console.log('Created team template:', template.id); ```bash curl -X GET "https://app.documenso.com/api/v2/template" \ - -H "Authorization: api_team_xxxxxxxxxxxxxxxx" + -H "Authorization: api_xxxxxxxxxxxxxxxx" ```` diff --git a/apps/docs/content/docs/self-hosting/deployment/docker.mdx b/apps/docs/content/docs/self-hosting/deployment/docker.mdx index 68508e767..d8ba9c70a 100644 --- a/apps/docs/content/docs/self-hosting/deployment/docker.mdx +++ b/apps/docs/content/docs/self-hosting/deployment/docker.mdx @@ -102,7 +102,7 @@ See [Email Configuration](/docs/self-hosting/configuration/email) for other tran | Variable | Description | Default | | ------------------------------------------- | -------------------------------------------------------------- | ------------------------- | | `PORT` | Port the application listens on | `3000` | -| `NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH` | Path to signing certificate inside container | `/opt/documenso/cert.p12` | +| `NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH` | Path to signing certificate inside container — set to the volume-mount path (e.g. `/opt/documenso/cert.p12`). Only Docker Compose defaults this; plain `docker run` must set it explicitly | - | | `NEXT_PRIVATE_SIGNING_PASSPHRASE` | Passphrase for the signing certificate | - | | `NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS` | Base64-encoded `.p12` certificate (alternative to file path) | - | | `NEXT_PUBLIC_UPLOAD_TRANSPORT` | Document storage: `database` or `s3` | `database` | @@ -136,6 +136,7 @@ docker run -d \ -e NEXT_PUBLIC_WEBAPP_URL="https://sign.example.com" \ -e NEXT_PRIVATE_INTERNAL_WEBAPP_URL="http://localhost:3000" \ -e NEXT_PRIVATE_DATABASE_URL="postgresql://user:password@db-host:5432/documenso" \ + -e NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH="/opt/documenso/cert.p12" \ -e NEXT_PRIVATE_SIGNING_PASSPHRASE="your-certificate-password" \ -e NEXT_PRIVATE_SMTP_TRANSPORT="smtp-auth" \ -e NEXT_PRIVATE_SMTP_HOST="smtp.example.com" \ @@ -154,6 +155,12 @@ A signing certificate is required for document signing. You have two options for - **Volume mount** — mount a `.p12` file from the host into the container at `/opt/documenso/cert.p12` (shown above). This is the simplest approach for small to moderate deployments. - **Base64-encoded contents** — set `NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS` with the base64-encoded certificate string. Use this when file mounting is not available (e.g., Railway, Vercel). + + Plain `docker run` deployments must set `NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH` explicitly. This + prevents production deployments from accidentally using the insecure example certificate. + Docker Compose sets the file path for you. + + For production deployments that require Adobe Approved Trust List recognition, consider using a [Google Cloud HSM](/docs/self-hosting/configuration/signing-certificate/google-cloud-hsm) or another external HSM. @@ -178,6 +185,7 @@ NEXT_PUBLIC_WEBAPP_URL=https://sign.example.com NEXT_PRIVATE_INTERNAL_WEBAPP_URL=http://localhost:3000 NEXT_PRIVATE_DATABASE_URL=postgresql://user:password@db-host:5432/documenso NEXT_PRIVATE_DIRECT_DATABASE_URL=postgresql://user:password@db-host:5432/documenso +NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH=/opt/documenso/cert.p12 NEXT_PRIVATE_SIGNING_PASSPHRASE=your-certificate-password NEXT_PRIVATE_SMTP_TRANSPORT=smtp-auth NEXT_PRIVATE_SMTP_HOST=smtp.example.com @@ -203,6 +211,12 @@ docker run -d \ Documenso provides health check endpoints for monitoring: + + If a certificate is mounted but signing fails, ensure `NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH` + explicitly points to its path inside the container. Production does not use the development + example certificate as a fallback. + + | Endpoint | Purpose | | ------------------------- | -------------------------------------------------------------- | | `/api/health` | Checks database connectivity and certificate status | diff --git a/apps/docs/content/docs/users/organisations/preferences/document.mdx b/apps/docs/content/docs/users/organisations/preferences/document.mdx index 1f4e82c08..d81252325 100644 --- a/apps/docs/content/docs/users/organisations/preferences/document.mdx +++ b/apps/docs/content/docs/users/organisations/preferences/document.mdx @@ -34,7 +34,7 @@ To access the preferences, navigate to either the organisation or teams settings | **Default Recipients** | Recipients that are automatically added to new documents. Can be overridden per document. | | **Default Envelope Expiration** | How long recipients have to sign before the signing link expires. See [recipient expiration](/docs/users/documents/advanced/recipient-expiration). | | **Default Signing Reminders** | When and how often to email recipients who have not yet signed. See [signing reminders](/docs/users/documents/advanced/signing-reminders). | -| **Delegate Document Ownership** | Allow team API tokens to delegate document ownership to another team member. | +| **Delegate Document Ownership** | By default, documents created with a team API token are owned by the user who created the token. Enable this setting to let supported API requests assign ownership to another team member. | | **AI Features** | Enable AI-powered features such as automatic recipient detection. Only shown if AI features are configured on the instance. | Document visibility, language, and signature settings can be overridden per document. diff --git a/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page-renderer.tsx b/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page-renderer.tsx index c9deb51ad..e82232311 100644 --- a/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page-renderer.tsx +++ b/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page-renderer.tsx @@ -38,6 +38,9 @@ import { useEffect, useMemo, useRef, useState } from 'react'; import { fieldButtonList } from './envelope-editor-fields-drag-drop'; import { EnvelopeRecipientSelectorCommand } from './envelope-recipient-selector'; +/** How far past a resize handle you can still grab it, in screen pixels. */ +const TRANSFORMER_ANCHOR_HIT_STROKE_PX = 24; + export const EnvelopeEditorFieldsPageRenderer = ({ pageData }: { pageData: PageRenderData }) => { const { t, i18n } = useLingui(); const analytics = useAnalytics(); @@ -359,6 +362,9 @@ export const EnvelopeEditorFieldsPageRenderer = ({ pageData }: { pageData: PageR shouldOverdrawWholeArea: true, ignoreStroke: true, flipEnabled: false, + anchorStyleFunc: (anchor) => { + anchor.hitStrokeWidth(TRANSFORMER_ANCHOR_HIT_STROKE_PX / scale); + }, boundBoxFunc: (oldBox, newBox) => { // Enforce minimum size if (newBox.width < 30 || newBox.height < 20) { diff --git a/docker/Dockerfile b/docker/Dockerfile index 0b5923a05..fa2be3083 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -76,6 +76,7 @@ COPY --from=builder /app/out/json/ . COPY --from=builder /app/out/package-lock.json ./package-lock.json COPY --from=builder /app/lingui.config.ts ./lingui.config.ts +COPY --from=builder /app/patches ./patches RUN npm ci @@ -114,6 +115,8 @@ WORKDIR /app COPY --from=builder --chown=nodejs:nodejs /app/out/json/ . # Copy the tailwind config files across COPY --from=builder --chown=nodejs:nodejs /app/out/full/packages/tailwind-config ./packages/tailwind-config +# Copy the patches across +COPY --from=builder --chown=nodejs:nodejs /app/patches ./patches RUN npm ci --only=production diff --git a/package-lock.json b/package-lock.json index cf266782c..5fa83778f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "dependencies": { "@ai-sdk/google-vertex": "5.0.48", "@documenso/prisma": "*", - "@libpdf/core": "^0.4.1", + "@libpdf/core": "^0.4.2", "@lingui/conf": "^5.6.0", "@lingui/core": "^5.6.0", "@marsidev/react-turnstile": "^1.5.0", @@ -4802,9 +4802,9 @@ "license": "MIT" }, "node_modules/@libpdf/core": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@libpdf/core/-/core-0.4.1.tgz", - "integrity": "sha512-DWGxWw1na8oFPixz+b6kOgu4tMD8xJLDgyPGVUNqIswO5POHAxsqmTvUvDW0IrwHP7kFRHBV3I3T/KhTABf9rA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@libpdf/core/-/core-0.4.2.tgz", + "integrity": "sha512-lbkIqLDZCCxjLpiC+8/Xvaru/ME7iVVoihl9tLqbp/CDUWZNF0q3u7s2tBJB9wRW/SzUWID6YPFvBWws770hrQ==", "license": "MIT", "dependencies": { "@noble/ciphers": "^2.2.0", diff --git a/package.json b/package.json index 4770c9eec..a8d78aed9 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "dependencies": { "@ai-sdk/google-vertex": "5.0.48", "@documenso/prisma": "*", - "@libpdf/core": "^0.4.1", + "@libpdf/core": "^0.4.2", "@lingui/conf": "^5.6.0", "@lingui/core": "^5.6.0", "@prisma/extension-read-replicas": "^0.4.1", diff --git a/packages/app-tests/e2e/templates/template-bulk-send.spec.ts b/packages/app-tests/e2e/templates/template-bulk-send.spec.ts new file mode 100644 index 000000000..70ec298ac --- /dev/null +++ b/packages/app-tests/e2e/templates/template-bulk-send.spec.ts @@ -0,0 +1,80 @@ +import { prisma } from '@documenso/prisma'; +import { seedTeam } from '@documenso/prisma/seed/teams'; +import { seedTemplate } from '@documenso/prisma/seed/templates'; +import { expect, test } from '@playwright/test'; +import { EnvelopeType } from '@prisma/client'; + +import { apiSignin } from '../fixtures/authentication'; +import { openDropdownMenu } from '../fixtures/generic'; + +test('[TEMPLATES]: bulk send via CSV from the table action dropdown', async ({ page }) => { + const { team, owner } = await seedTeam(); + + await seedTemplate({ + title: 'Bulk send template', + userId: owner.id, + teamId: team.id, + }); + + const uniqueRecipientEmail = `bulk-send-${Date.now()}@documenso.com`; + + await apiSignin({ + page, + email: owner.email, + redirectPath: `/t/${team.url}/templates`, + }); + + const actionBtn = page + .getByRole('row', { name: 'Bulk send template' }) + .getByRole('cell', { name: 'Use Template' }) + .getByRole('button') + .nth(1); + + await openDropdownMenu(page, actionBtn); + + await page.getByText('Bulk Send via CSV').click(); + + const dialog = page.getByRole('dialog').filter({ hasText: 'Bulk Send Template via CSV' }); + + await expect(dialog).toBeVisible(); + + // Opening the native file picker blurs the window. Radix dropdown menus close themselves on + // window blur, which used to unmount this dialog when it was nested inside the menu content, + // silently discarding the user's file selection. + await page.evaluate(() => window.dispatchEvent(new Event('blur'))); + + await expect(dialog).toBeVisible(); + + const csv = ['recipient_1_email,recipient_1_name', `${uniqueRecipientEmail},Bulk Recipient`].join('\n'); + + await dialog.locator('input[type="file"]').setInputFiles({ + name: 'bulk-send.csv', + mimeType: 'text/csv', + buffer: Buffer.from(csv), + }); + + await expect(dialog.getByText('bulk-send.csv')).toBeVisible(); + + await dialog.getByRole('button', { name: 'Upload and Process' }).click(); + + await expect(page.getByText('Your bulk send has been initiated').first()).toBeVisible(); + + // The bulk send runs as a background job, so poll for the created document. + await expect + .poll( + async () => + await prisma.envelope.count({ + where: { + type: EnvelopeType.DOCUMENT, + teamId: team.id, + recipients: { + some: { + email: uniqueRecipientEmail, + }, + }, + }, + }), + { timeout: 30_000 }, + ) + .toBe(1); +}); diff --git a/packages/lib/translations/pl/web.po b/packages/lib/translations/pl/web.po index f9eeddd0d..207cae377 100644 --- a/packages/lib/translations/pl/web.po +++ b/packages/lib/translations/pl/web.po @@ -8,7 +8,7 @@ msgstr "" "Language: pl\n" "Project-Id-Version: documenso-app\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2026-08-13 14:22\n" +"PO-Revision-Date: 2026-08-27 12:58\n" "Last-Translator: \n" "Language-Team: Polish\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" @@ -316,7 +316,7 @@ msgstr "Sprawdź i {recipientActionVerb} dokument „{1}” utworzony przez zesp #: apps/remix/app/components/general/settings-upsell/branding-upsell.tsx #: apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx msgid "{0} has invited you to sign this document." -msgstr "" +msgstr "Organizacja {0} zaprosiła Cię do podpisania dokumentu." #. placeholder {0}: team.name #: packages/lib/jobs/definitions/emails/send-signing-email.handler.ts @@ -442,7 +442,7 @@ msgstr "Sprawdź i {action} dokument „{documentName}” utworzony przez użytk #: apps/remix/app/components/dialogs/envelopes-bulk-download-dialog.tsx msgid "{MAX_BULK_DOWNLOAD_ENVELOPES, plural, one {You can download up to # document at a time. Deselect some documents to continue.} other {You can download up to # documents at a time. Deselect some documents to continue.}}" -msgstr "" +msgstr "{MAX_BULK_DOWNLOAD_ENVELOPES, plural, one {Możesz pobrać jednocześnie # dokument. Odznacz niektóre dokumenty.} few {Możesz pobrać jednocześnie # dokumenty. Odznacz niektóre dokumenty.} many {Możesz pobrać jednocześnie # dokumentów. Odznacz niektóre dokumenty.} other {Możesz pobrać jednocześnie # dokumentów. Odznacz niektóre dokumenty.}}" #: apps/remix/app/components/dialogs/passkey-create-dialog.tsx msgid "{MAXIMUM_PASSKEYS, plural, one {You cannot have more than # passkey.} other {You cannot have more than # passkeys.}}" @@ -525,11 +525,11 @@ msgstr "Sprawdź i {action} dokument „{documentName}” utworzony przez zespó #: apps/remix/app/components/general/app-command-menu.tsx msgid "{totalVisibleCount, plural, one {# item} other {# items}}" -msgstr "" +msgstr "{totalVisibleCount, plural, one {# element} few {# elementy} many {# elementów} other {# elementów}}" #: apps/remix/app/components/general/app-command-menu.tsx msgid "{totalVisibleCount, plural, one {# result} other {# results}}" -msgstr "" +msgstr "{totalVisibleCount, plural, one {# wynik} few {# wyniki} many {# wyników} other {# wyników}}" #: packages/lib/utils/document-audit-logs.ts msgid "{user} added a field" @@ -1237,7 +1237,7 @@ msgstr "Konto zostało rozłączone" #: apps/remix/app/components/general/settings-upsell/sso-portal-upsell.tsx msgid "Accounts are automatically added to your organisation on sign-in" -msgstr "" +msgstr "Automatyczne dodawanie kont do organizacji podczas logowania" #: apps/remix/app/routes/_unauthenticated+/articles.signature-disclosure.tsx msgid "Acknowledgment" @@ -2455,7 +2455,7 @@ msgstr "Obramowanie" #: apps/remix/app/components/dialogs/branding-preferences-reset-dialog.tsx msgid "Border radius" -msgstr "Zaokrąglenia obramowania" +msgstr "Zaokrąglenie obramowania" #: apps/remix/app/components/forms/branding-preferences-form.tsx msgid "Border Radius" @@ -2471,7 +2471,7 @@ msgstr "Dół" #: apps/remix/app/components/general/settings-upsell/branding-upsell.tsx msgid "Brand accent" -msgstr "" +msgstr "Kolor marki" #: apps/remix/app/components/forms/branding-preferences-form.tsx msgid "Brand Colours" @@ -2479,7 +2479,7 @@ msgstr "Kolory marki" #: apps/remix/app/components/dialogs/branding-preferences-reset-dialog.tsx msgid "Brand colours, including background, foreground, primary, and border colours" -msgstr "Kolorów marki, w tym kolorów tła, przycisków i obramowań" +msgstr "Kolory marki, w tym kolory tła, przycisków i obramowań" #: apps/remix/app/components/forms/branding-preferences-form.tsx msgid "Brand Details" @@ -2491,7 +2491,7 @@ msgstr "Strona internetowa marki" #: apps/remix/app/components/dialogs/branding-preferences-reset-dialog.tsx msgid "Brand website and brand details" -msgstr "Strony internetowej i szczegółów marki" +msgstr "Strona internetowa i szczegóły marki" #: apps/remix/app/components/general/admin-global-settings-section.tsx #: packages/lib/utils/settings-nav.ts @@ -2581,7 +2581,7 @@ msgstr "Akceptując prośbę, umożliwisz zespołowi <0>{teamName}:" #: apps/remix/app/components/dialogs/envelope-delete-dialog.tsx msgid "By deleting this document, the following will occur:" -msgstr "Usunięcie dokumentu spowoduje następujące skutki:" +msgstr "Po usunięciu dokumentu:" #: apps/remix/app/components/general/document-signing/document-signing-auth-2fa.tsx msgid "By enabling 2FA, you will be required to enter a code from your authenticator app every time you sign in using email password." @@ -3008,11 +3008,11 @@ msgstr "Komunikacja" #: apps/remix/app/components/general/settings-upsell/branding-upsell.tsx msgid "Company details" -msgstr "" +msgstr "Szczegóły firmy" #: apps/remix/app/components/general/settings-upsell/branding-upsell.tsx msgid "Company details and website in email footers" -msgstr "" +msgstr "Szczegóły firmy i strona internetowa w stopkach" #: apps/remix/app/components/dialogs/organisation-create-dialog.tsx msgid "Compare all plans and features in detail" @@ -3203,7 +3203,7 @@ msgstr "Informacje kontaktowe" #: apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx #: apps/remix/app/components/general/settings-upsell/sso-portal-upsell.tsx msgid "Contact Sales" -msgstr "" +msgstr "Skontaktuj się z działem sprzedaży" #: apps/remix/app/components/dialogs/organisation-create-dialog.tsx msgid "Contact sales here" @@ -3215,7 +3215,7 @@ msgstr "Skontaktuj się z nami" #: apps/remix/app/components/general/settings-upsell/settings-upsell-card.tsx msgid "Contact your organisation owner to upgrade plans." -msgstr "" +msgstr "Skontaktuj się z właścicielem organizacji, aby zaktualizować plan." #: apps/remix/app/components/general/admin-site-banner-section.tsx msgid "Content" @@ -3271,7 +3271,7 @@ msgstr "Przejdź do logowania" #: apps/remix/app/components/general/settings-upsell/sso-portal-upsell.tsx msgid "Continue with SSO" -msgstr "" +msgstr "Logowanie SSO" #: apps/remix/app/components/forms/reminder-preferences-form.tsx msgid "Controls how long recipients have to complete signing before the document expires. After expiration, recipients can no longer sign the document." @@ -3718,11 +3718,11 @@ msgstr "Niestandardowy plik {0} MB" #: apps/remix/app/components/dialogs/branding-preferences-reset-dialog.tsx msgid "Custom branding enabled setting" -msgstr "Niestandardowych ustawień marki" +msgstr "Niestandardowe ustawienia marki" #: apps/remix/app/components/dialogs/branding-preferences-reset-dialog.tsx msgid "Custom CSS" -msgstr "Niestandardowego CSS" +msgstr "Niestandardowy CSS" #: apps/remix/app/components/forms/branding-preferences-form.tsx msgid "Custom CSS is sanitised on save. Layout-breaking properties, remote URLs, and pseudo-elements are stripped automatically. Any rules dropped during sanitisation will be shown after you save." @@ -4376,7 +4376,7 @@ msgstr "Wszystkie dokumenty" #: apps/remix/app/utils/toast-error-messages.ts msgid "Document already completed" -msgstr "" +msgstr "Dokument został już zakończony" #: apps/remix/app/components/general/envelope-signing/envelope-signing-complete-dialog.tsx msgid "Document already signed" @@ -4565,7 +4565,7 @@ msgstr "Przeniesiono dokument do zespołu" #: apps/remix/app/utils/toast-error-messages.ts msgid "Document no longer available" -msgstr "" +msgstr "Dokument nie jest już dostępny" #: apps/remix/app/routes/_recipient+/sign.$token+/complete.tsx msgid "Document no longer available to sign" @@ -4573,7 +4573,7 @@ msgstr "Dokument nie jest już dostępny do podpisania" #: apps/remix/app/utils/toast-error-messages.ts msgid "Document not ready" -msgstr "" +msgstr "Dokument nie jest gotowy" #: packages/lib/utils/document-audit-logs.ts msgctxt "Audit log format" @@ -5033,7 +5033,7 @@ msgstr "np. Resend (plan darmowy)" #: apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx msgid "Easy DNS setup with auto-generated DKIM and SPF records" -msgstr "" +msgstr "Łatwa konfiguracja DNS z automatycznie generowanymi rekordami DKIM i SPF" #: apps/remix/app/components/general/document/document-page-view-button.tsx #: apps/remix/app/components/general/document/document-page-view-dropdown.tsx @@ -5709,7 +5709,7 @@ msgstr "Wystąpił błąd podczas przesyłania pliku" #: apps/remix/app/components/general/app-command-menu.tsx msgid "esc" -msgstr "escape" +msgstr "esc" #: apps/remix/app/components/general/webhook-logs-sheet.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/settings.webhooks.$id._index.tsx @@ -6202,7 +6202,7 @@ msgstr "Niemiecki" #: apps/remix/app/components/general/settings-upsell/sso-portal-upsell.tsx msgid "Give your members a dedicated single sign-on portal. The SSO portal is available on the Enterprise plan." -msgstr "" +msgstr "Zapewnij swoim użytkownikom logowanie SSO. Funkcja dostępna w planie Enterprise." #: apps/remix/app/components/general/app-command-menu.tsx #: apps/remix/app/components/general/app-command-menu.tsx @@ -6438,7 +6438,7 @@ msgstr "Ukryj" #: packages/ui/components/document/envelope-recipient-field-tooltip.tsx msgid "Hide field" -msgstr "" +msgstr "Ukryj pole" #: apps/remix/app/components/general/admin-license-card.tsx msgid "Hide license key" @@ -6852,7 +6852,7 @@ msgstr "To nie jest Twoja kolej na podpisanie dokumentu. Gdy nadejdzie Twoja kol #: apps/remix/app/utils/toast-error-messages.ts msgid "It's not your turn to sign yet" -msgstr "" +msgstr "To nie jest Twoja kolej na podpisanie dokumentu" #: packages/lib/constants/i18n.ts msgid "Italian" @@ -6974,7 +6974,7 @@ msgstr "Użyto" #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/settings.tokens.tsx msgid "Last Used" -msgstr "" +msgstr "Użyto" #: apps/remix/app/routes/_authenticated+/admin+/email-domains._index.tsx #: apps/remix/app/routes/_authenticated+/admin+/email-domains.$id.tsx @@ -7603,7 +7603,7 @@ msgstr "Ustawienia nazwy" #: apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx msgid "Named senders with defaults per team, template or document" -msgstr "" +msgstr "Zdefiniowani nadawcy z domyślnymi ustawieniami dla zespołu, szablonu lub dokumentu" #: apps/remix/app/components/general/app-command-menu.tsx msgid "Navigate" @@ -7990,14 +7990,14 @@ msgstr "Na tej stronie możesz utworzyć nowe webhooki i zarządzać obecnymi." #: apps/remix/app/components/dialogs/branding-preferences-reset-dialog.tsx #: apps/remix/app/components/dialogs/document-preferences-reset-dialog.tsx msgid "Once confirmed, the following will be reset:" -msgstr "Potwierdzenie akcji spowoduje zresetowanie:" +msgstr "Po potwierdzeniu zresetowane zostaną:" #: apps/remix/app/components/dialogs/envelope-cancel-dialog.tsx #: apps/remix/app/components/dialogs/envelope-delete-dialog.tsx #: apps/remix/app/components/dialogs/envelopes-bulk-cancel-dialog.tsx #: apps/remix/app/components/dialogs/envelopes-bulk-delete-dialog.tsx msgid "Once confirmed, the following will occur:" -msgstr "Potwierdzenie akcji spowoduje następujące skutki:" +msgstr "Po potwierdzeniu:" #: packages/lib/constants/template.ts msgid "Once enabled, you can select any active recipient to be a direct link signing recipient, or create a new one. This recipient type cannot be edited or deleted." @@ -8021,7 +8021,7 @@ msgstr "Jeden z dokumentów ma niezgodną rolę w procesie podpisywania." #: apps/remix/app/utils/toast-error-messages.ts msgid "One or more of your required fields have not been saved. Please refresh the page, complete any empty required fields, and try again." -msgstr "" +msgstr "Co najmniej jedno z wymaganych pól nie zostało zapisane. Odśwież stronę, uzupełnij wymagane pola i spróbuj ponownie." #: apps/remix/app/components/forms/document-preferences-form.tsx msgid "Only admins can access and view the document" @@ -8756,7 +8756,7 @@ msgstr "Wybierz, w jaki sposób chcesz otrzymać swój kod weryfikacyjny." #: apps/remix/app/components/general/settings-upsell/branding-upsell.tsx #: apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx msgid "Please sign: Example.pdf" -msgstr "" +msgstr "Podpisz dokument: umowa.pdf" #: apps/remix/app/components/dialogs/organisation-email-domain-create-dialog.tsx msgid "Please try a different domain." @@ -8789,6 +8789,10 @@ msgstr "Prześlij dokument, aby kontynuować" msgid "Please upload a logo" msgstr "Prześlij logo" +#: packages/ui/primitives/signature-pad/signature-pad-upload.tsx +msgid "Please upload a valid image file." +msgstr "Prześlij prawidłową grafikę." + #: packages/lib/constants/i18n.ts msgid "Polish" msgstr "Polski" @@ -8946,7 +8950,7 @@ msgstr "Szablony publiczne są powiązane z Twoim profilem publicznym. Wszelkie #: apps/remix/app/components/general/settings-upsell/branding-upsell.tsx msgid "Put your own brand on every document you send. Branding is available on the Teams plan and above." -msgstr "" +msgstr "Umieść swoje logo na każdym wysyłanym dokumencie. Branding jest dostępny w planie Teams i wyższym." #: apps/remix/app/components/general/envelope-editor/envelope-editor.tsx msgid "Quick Actions" @@ -9278,7 +9282,7 @@ msgstr "Przekierowywanie do {0}..." #: apps/remix/app/components/general/settings-upsell/sso-portal-upsell.tsx msgid "Redirecting to your identity provider" -msgstr "" +msgstr "Przekierowywanie do dostawcy tożsamości" #: apps/remix/app/components/forms/signup.tsx #: apps/remix/app/components/general/claim-account.tsx @@ -9650,7 +9654,7 @@ msgstr "Zapewniamy, że Twój dokument jest poufny i nigdy nie zostanie udostęp #: apps/remix/app/components/general/settings-upsell/sso-portal-upsell.tsx msgid "Restrict sign-ins by email domain and choose the default role" -msgstr "" +msgstr "Ogranicz logowanie do wybranych domen i przypisz domyślną rolę" #: apps/remix/app/components/general/organisations/organisation-billing-banner.tsx msgid "Restricted Access" @@ -9814,7 +9818,7 @@ msgstr "Szukaj identyfikatora lub nazwy" #: apps/remix/app/routes/_authenticated+/admin+/documents._index.tsx msgid "Search by document title, recipient:123, team:123 or user:123" -msgstr "" +msgstr "Szukaj tytułu dokumentu, odbiorcy, zespołu lub użytkownika" #: apps/remix/app/routes/_authenticated+/admin+/email-domains._index.tsx msgid "Search by domain or organisation name" @@ -10112,7 +10116,7 @@ msgstr "Wybierz widoczność" #: apps/remix/app/components/tables/envelopes-table-bulk-action-bar.tsx msgid "selected" -msgstr "" +msgstr "zaznaczono" #: apps/remix/app/components/dialogs/envelopes-bulk-delete-dialog.tsx msgid "Selected documents will be permanently deleted" @@ -10170,7 +10174,7 @@ msgstr "Wyślij dokument" #: apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx msgid "Send documents from your own domain. Email domains are available on the Enterprise plan." -msgstr "" +msgstr "Wysyłaj dokumenty ze swojej domeny. Domeny są dostępne w planie Enterprise." #: packages/email/templates/confirm-team-email.tsx msgid "Send documents on behalf of the team using the email address" @@ -10182,7 +10186,7 @@ msgstr "Wyślij dokumenty do odbiorców natychmiast" #: apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx msgid "Send emails to recipients from your domain" -msgstr "" +msgstr "Wysyłaj wiadomości ze swojej domeny" #: apps/remix/app/components/general/envelope-editor/envelope-editor.tsx msgid "Send Envelope" @@ -10232,11 +10236,11 @@ msgstr "Nadawca został zgłoszony" #: apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx msgid "Sending from app.documenso.com" -msgstr "" +msgstr "Wysyłanie z app.documenso.com" #: apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx msgid "Sending from your domain" -msgstr "" +msgstr "Wysyłanie z Twojej domeny" #: apps/remix/app/components/forms/forgot-password.tsx msgid "Sending Reset Email..." @@ -10260,7 +10264,7 @@ msgstr "Wysłano w tym okresie" #: apps/remix/app/components/general/settings-upsell/branding-upsell.tsx msgid "Separate branding per team" -msgstr "" +msgstr "Oddzielny branding dla zespołów" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Session revoked" @@ -10501,6 +10505,7 @@ msgid "Signature ID" msgstr "Identyfikator podpisu" #: packages/ui/primitives/signature-pad/signature-pad-draw.tsx +#: packages/ui/primitives/signature-pad/signature-pad-upload.tsx msgid "Signature is too small" msgstr "Podpis jest zbyt mały" @@ -10541,7 +10546,7 @@ msgstr "Podpisany" #: apps/remix/app/components/general/settings-upsell/sso-portal-upsell.tsx msgid "Signed in" -msgstr "" +msgstr "Zalogowano" #: apps/remix/app/components/general/envelope-signing/envelope-signer-header.tsx msgid "Signer" @@ -10609,7 +10614,7 @@ msgstr "Logowanie..." #: apps/remix/app/utils/toast-error-messages.ts msgid "Signing link expired" -msgstr "" +msgstr "Link do podpisywania wygasł" #: apps/remix/app/components/general/document/document-page-view-dropdown.tsx #: apps/remix/app/components/tables/documents-table-action-dropdown.tsx @@ -10665,7 +10670,7 @@ msgstr "Od {0}" #: apps/remix/app/components/general/settings-upsell/sso-portal-upsell.tsx msgid "Single sign-on" -msgstr "" +msgstr "Logowanie SSO" #: apps/remix/app/components/general/admin-site-banner-section.tsx msgid "Site Banner" @@ -10688,7 +10693,7 @@ msgstr "Niektóre pola są umieszczone jedno nad drugim. Może to utrudnić podp #: apps/remix/app/utils/toast-error-messages.ts msgid "Some fields were not saved" -msgstr "" +msgstr "Niektóre pola nie zostały zapisane" #: apps/remix/app/components/general/app-command-menu.tsx msgid "Some searches failed — results may be incomplete." @@ -11605,7 +11610,7 @@ msgstr "Dokument został odrzucony w zewnętrznej usłudze w imieniu odbiorcy" #: apps/remix/app/components/dialogs/envelope-delete-dialog.tsx msgid "The document will be hidden from your account" -msgstr "Dokument zostanie ukryty w Twoim koncie" +msgstr "Dokument zostanie ukryty na Twoim koncie" #: apps/remix/app/components/dialogs/template-use-dialog.tsx msgid "The document will be immediately sent to recipients if this is checked." @@ -11697,6 +11702,14 @@ msgstr "Brak pola podpisu dla następujących podpisujących:" msgid "The following team has been deleted. You will no longer be able to access this team and its documents" msgstr "Następujący zespół został usunięty. Nie będziesz mógł już uzyskać dostępu do tego zespołu i jego dokumentów" +#: packages/ui/primitives/signature-pad/signature-pad-upload.tsx +msgid "The image could not be loaded. Please try again." +msgstr "Nie można załadować grafiki. Spróbuj ponownie." + +#: packages/ui/primitives/signature-pad/signature-pad-upload.tsx +msgid "The image must be smaller than 5MB." +msgstr "Maksymalny rozmiar grafiki to 5 MB." + #: apps/remix/app/components/general/admin-license-card.tsx msgid "The license key has been copied to your clipboard" msgstr "Klucz licencyjny został skopiowany do schowka" @@ -12027,7 +12040,7 @@ msgstr "Szablon bezpośredniego linku nie może zostać użyty, ponieważ co naj #: apps/remix/app/utils/toast-error-messages.ts msgid "This document can no longer be signed. It may have been removed by the sender, or your signing access may have been revoked. Please contact the sender for a new signing link." -msgstr "" +msgstr "Nie można podpisać dokumentu. Być może został on usunięty przez nadawcę lub Twoje uprawnienia do podpisywania zostały unieważnione. Skontaktuj się z nadawcą, aby uzyskać nowy link do podpisywania." #: packages/email/template-components/template-document-super-delete.tsx msgid "This document can not be recovered, if you would like to dispute the reason for future documents please contact support." @@ -12059,7 +12072,7 @@ msgstr "Nie można zapisać dokumentu jako szablonu. Spróbuj ponownie." #: apps/remix/app/utils/toast-error-messages.ts msgid "This document has already been completed and no further signatures can be added." -msgstr "" +msgstr "Dokument został już zakończony i nie wymaga kolejnych podpisów." #: apps/remix/app/components/general/envelope-editor/envelope-recipient-selector.tsx #: packages/ui/primitives/recipient-selector.tsx @@ -12081,7 +12094,7 @@ msgstr "Dokument został anulowany przez właściciela." #: apps/remix/app/utils/toast-error-messages.ts msgid "This document has been cancelled by the sender and can no longer be signed. Please contact the sender if you believe this is a mistake." -msgstr "" +msgstr "Dokument został anulowany przez nadawcę i nie można go już podpisać. Jeśli uważasz to za błąd, skontaktuj się z nadawcą." #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx msgid "This document has been rejected by a recipient" @@ -12089,7 +12102,7 @@ msgstr "Dokument został odrzucony przez odbiorcę" #: apps/remix/app/utils/toast-error-messages.ts msgid "This document has been rejected by a recipient and can no longer be signed." -msgstr "" +msgstr "Dokument został odrzucony przez odbiorcę i nie można go już podpisać." #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx msgid "This document has been signed by all recipients" @@ -12097,7 +12110,7 @@ msgstr "Dokument został podpisany przez wszystkich odbiorców" #: apps/remix/app/utils/toast-error-messages.ts msgid "This document has not been sent for signing yet. Please wait for the sender to send it before signing." -msgstr "" +msgstr "Dokument nie został jeszcze wysłany do podpisania. Poczekaj na wysłanie go przez nadawcę." #: apps/remix/app/utils/toast-error-messages.ts msgid "This document has too many recipients. Please remove some recipients or contact support if you need more." @@ -12113,7 +12126,7 @@ msgstr "Dokument jest szkicem i nie został wysłany" #: apps/remix/app/utils/toast-error-messages.ts msgid "This document is signed in a set order and other recipients must sign before you. You will receive an email when it is your turn." -msgstr "" +msgstr "Dokument jest podpisywany zgodnie z ustaloną kolejnością. Gdy nadejdzie Twoja kolej, otrzymasz wiadomość." #: apps/remix/app/components/general/legacy-field-warning-popover.tsx msgid "This document is using legacy field insertion, we recommend using the new field insertion method for more accurate results." @@ -12192,6 +12205,10 @@ msgstr "Typ pliku nie jest obsługiwany. Prześlij dokument PDF lub Word." msgid "This folder contains multiple items. Deleting it will remove all subfolders and move all nested documents and templates to the root folder." msgstr "Folder zawiera wiele elementów. Usunięcie go spowoduje przeniesienie wszystkich dokumentów i szablonów znajdujących się w tym folderze do folderu głównego." +#: packages/ui/primitives/signature-pad/signature-pad-upload.tsx +msgid "This image is invalid, please upload a valid image file." +msgstr "Grafika jest nieprawidłowa. Prześlij prawidłowy plik." + #: apps/remix/app/components/general/envelope-editor/envelope-editor-settings-dialog.tsx #: packages/ui/primitives/template-flow/add-template-settings.tsx msgid "This is how the document will reach the recipients once the document is ready for signing." @@ -12774,6 +12791,10 @@ msgstr "Nie można się zalogować" msgid "Unable to start the signing flow" msgstr "Nie można rozpocząć procesu podpisywania" +#: packages/ui/primitives/signature-pad/signature-pad-upload.tsx +msgid "Unable to upload image" +msgstr "Nie można przesłać grafiki" + #: apps/remix/app/components/general/document-signing/document-signing-auth-2fa.tsx #: apps/remix/app/components/general/document-signing/document-signing-auth-passkey.tsx #: apps/remix/app/components/general/document-signing/document-signing-auth-password.tsx @@ -12788,6 +12809,7 @@ msgstr "Niezakończono" #: apps/remix/app/components/forms/form-sticky-save-bar.tsx #: packages/ui/primitives/signature-pad/signature-pad-draw.tsx +#: packages/ui/primitives/signature-pad/signature-pad-draw.tsx msgid "Undo" msgstr "Cofnij" @@ -12832,15 +12854,15 @@ msgstr "Rozłącz" #: apps/remix/app/components/general/settings-upsell/branding-upsell.tsx msgid "Unlock Branding Preferences" -msgstr "" +msgstr "Odblokuj ustawienia brandingu" #: apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx msgid "Unlock Email Domains" -msgstr "" +msgstr "Odblokuj domeny" #: apps/remix/app/components/general/settings-upsell/sso-portal-upsell.tsx msgid "Unlock the Organisation SSO Portal" -msgstr "" +msgstr "Odblokuj logowanie SSO organizacji" #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Unpin" @@ -13017,7 +13039,7 @@ msgstr "Ulepsz organizację <0>{0} do planu {planName}" #: apps/remix/app/components/general/settings-upsell/settings-upsell-card.tsx msgid "Upgrade Plan" -msgstr "" +msgstr "Ulepsz plan" #: apps/remix/app/components/general/envelope/envelope-drop-zone-wrapper.tsx msgid "Upgrade your plan to upload more documents" @@ -13078,6 +13100,10 @@ msgstr "Prześlij dokumenty i dodaj odbiorców" msgid "Upload failed" msgstr "Przesyłanie nie powiodło się" +#: packages/ui/primitives/signature-pad/signature-pad-upload.tsx +msgid "Upload New Image" +msgstr "Prześlij nową grafikę" + #: apps/remix/app/components/general/admin-global-settings-section.tsx msgid "Upload signature" msgstr "Podpis przesyłany" @@ -13506,7 +13532,7 @@ msgstr "Oczekiwanie na innych" #: packages/lib/jobs/definitions/emails/send-document-pending-email.handler.ts msgid "Waiting for others to complete signing" -msgstr "" +msgstr "Oczekiwanie na zakończenie podpisywania przez innych" #: apps/remix/app/routes/_recipient+/sign.$token+/complete.tsx msgid "Waiting for others to sign" @@ -14004,7 +14030,7 @@ msgstr "Witaj z powrotem! Oto podsumowanie Twojego konta." #. placeholder {0}: organisation.name #: apps/remix/app/components/general/settings-upsell/sso-portal-upsell.tsx msgid "Welcome to {0}" -msgstr "" +msgstr "Witaj w organizacji {0}" #: apps/remix/app/routes/_unauthenticated+/o.$orgUrl.signin.tsx msgid "Welcome to {organisationName}" @@ -14085,7 +14111,7 @@ msgstr "W ramach limitu" #: apps/remix/app/components/general/settings-upsell/sso-portal-upsell.tsx msgid "Works with any OIDC provider — Okta, Entra ID, Google and more" -msgstr "" +msgstr "Działa z dowolnym dostawcą OIDC: Okta, Entra ID, Google i więcej" #: apps/remix/app/components/forms/public-profile-form.tsx msgid "Write a description to display on your public profile" @@ -15102,7 +15128,7 @@ msgstr "Koperta została ponownie wysłana." #: apps/remix/app/components/general/settings-upsell/branding-upsell.tsx msgid "Your logo on signing pages and emails" -msgstr "" +msgstr "Twoje logo na stronach podpisywania i w wiadomościach" #: apps/remix/app/components/general/document-signing/document-signing-complete-dialog.tsx msgid "Your Name" @@ -15239,7 +15265,7 @@ msgstr "Certyfikat podpisu jest nieważny, wygasł lub brakuje w nim wymaganego #: apps/remix/app/utils/toast-error-messages.ts msgid "Your signing link has expired. Please contact the sender to request a new one." -msgstr "" +msgstr "Twój link do podpisywania wygasł. Skontaktuj się z nadawcą, aby otrzymać nowy link." #: packages/lib/utils/document-audit-logs.ts msgid "Your signing provider authentication failed" @@ -15322,3 +15348,14 @@ msgstr "Twój kod weryfikacyjny:" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.sso.tsx msgid "your-domain.com another-domain.com" msgstr "twoja-domena.pl inna-domena.pl" + +#: packages/ui/primitives/signature-pad/signature-pad-upload.tsx +#: packages/ui/primitives/signature-pad/signature-pad-upload.tsx +msgid "Zoom in" +msgstr "Powiększ" + +#: packages/ui/primitives/signature-pad/signature-pad-upload.tsx +#: packages/ui/primitives/signature-pad/signature-pad-upload.tsx +msgid "Zoom out" +msgstr "Pomniejsz" + diff --git a/packages/ui/primitives/dropdown-menu.tsx b/packages/ui/primitives/dropdown-menu.tsx index 98109c460..9c5bdd16e 100644 --- a/packages/ui/primitives/dropdown-menu.tsx +++ b/packages/ui/primitives/dropdown-menu.tsx @@ -4,6 +4,19 @@ import * as React from 'react'; import { cn } from '../lib/utils'; +/** + * Note: The underlying @radix-ui/react-menu package is patched, see + * patches/@radix-ui+react-menu+2.1.24.patch. + * + * Since @radix-ui/react-menu 2.1.18, Radix closes any open menu when the window fires a + * "blur" event. Opening a native file picker blurs the window, which would close the + * menu and unmount anything rendered within its content, such as dialogs containing + * file inputs, silently discarding the user's file selection. The patch removes that + * behaviour since there is currently no native prop to opt out of it, see + * https://github.com/radix-ui/primitives/issues/3618. + * + * Regression test: packages/app-tests/e2e/templates/template-bulk-send.spec.ts + */ const DropdownMenu = DropdownMenuPrimitive.Root; const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; diff --git a/patches/@radix-ui+react-menu+2.1.24.patch b/patches/@radix-ui+react-menu+2.1.24.patch new file mode 100644 index 000000000..4b5dfe850 --- /dev/null +++ b/patches/@radix-ui+react-menu+2.1.24.patch @@ -0,0 +1,44 @@ +diff --git a/node_modules/@radix-ui/react-menu/dist/index.js b/node_modules/@radix-ui/react-menu/dist/index.js +index b3f6113..d8ec2e3 100644 +--- a/node_modules/@radix-ui/react-menu/dist/index.js ++++ b/node_modules/@radix-ui/react-menu/dist/index.js +@@ -139,9 +139,14 @@ var Menu = /* @__PURE__ */ __name((props) => { + if (!open) { + return; + } +- const handleBlur = /* @__PURE__ */ __name(() => handleOpenChange(false), "handleBlur"); +- window.addEventListener("blur", handleBlur); +- return () => window.removeEventListener("blur", handleBlur); ++ // DOCUMENSO PATCH: @radix-ui/react-menu 2.1.18+ closes open menus when the window ++ // fires a "blur" event. Opening a native file picker blurs the window, which closes ++ // the menu and unmounts anything rendered within its content, such as dialogs that ++ // contain file inputs, silently discarding the user's file selection. This restores ++ // the pre-2.1.18 behaviour. Regression test: e2e/templates/template-bulk-send.spec.ts ++ // const handleBlur = () => handleOpenChange(false); ++ // window.addEventListener("blur", handleBlur); ++ // return () => window.removeEventListener("blur", handleBlur); + }, [open, handleOpenChange]); + return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PopperPrimitive.Root, { ...popperScope, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( + MenuProvider, +diff --git a/node_modules/@radix-ui/react-menu/dist/index.mjs b/node_modules/@radix-ui/react-menu/dist/index.mjs +index cd4303a..68865e3 100644 +--- a/node_modules/@radix-ui/react-menu/dist/index.mjs ++++ b/node_modules/@radix-ui/react-menu/dist/index.mjs +@@ -73,9 +73,14 @@ var Menu = /* @__PURE__ */ __name((props) => { + if (!open) { + return; + } +- const handleBlur = /* @__PURE__ */ __name(() => handleOpenChange(false), "handleBlur"); +- window.addEventListener("blur", handleBlur); +- return () => window.removeEventListener("blur", handleBlur); ++ // DOCUMENSO PATCH: @radix-ui/react-menu 2.1.18+ closes open menus when the window ++ // fires a "blur" event. Opening a native file picker blurs the window, which closes ++ // the menu and unmounts anything rendered within its content, such as dialogs that ++ // contain file inputs, silently discarding the user's file selection. This restores ++ // the pre-2.1.18 behaviour. Regression test: e2e/templates/template-bulk-send.spec.ts ++ // const handleBlur = () => handleOpenChange(false); ++ // window.addEventListener("blur", handleBlur); ++ // return () => window.removeEventListener("blur", handleBlur); + }, [open, handleOpenChange]); + return /* @__PURE__ */ jsx(PopperPrimitive.Root, { ...popperScope, children: /* @__PURE__ */ jsx( + MenuProvider,