-
+
{template.publicTitle}
-
{template.publicDescription}
+
{template.publicDescription}
diff --git a/apps/remix/app/components/tables/settings-security-activity-table.tsx b/apps/remix/app/components/tables/settings-security-activity-table.tsx
index 18bba7d62..79cb0fc66 100644
--- a/apps/remix/app/components/tables/settings-security-activity-table.tsx
+++ b/apps/remix/app/components/tables/settings-security-activity-table.tsx
@@ -1,12 +1,3 @@
-import { useMemo } from 'react';
-
-import { msg } from '@lingui/core/macro';
-import { useLingui } from '@lingui/react';
-import type { DateTimeFormatOptions } from 'luxon';
-import { DateTime } from 'luxon';
-import { useLocation, useNavigate, useSearchParams } from 'react-router';
-import { UAParser } from 'ua-parser-js';
-
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { USER_SECURITY_AUDIT_LOG_MAP } from '@documenso/lib/constants/auth';
import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params';
@@ -16,6 +7,13 @@ import { DataTable } from '@documenso/ui/primitives/data-table';
import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination';
import { Skeleton } from '@documenso/ui/primitives/skeleton';
import { TableCell } from '@documenso/ui/primitives/table';
+import { msg } from '@lingui/core/macro';
+import { useLingui } from '@lingui/react';
+import type { DateTimeFormatOptions } from 'luxon';
+import { DateTime } from 'luxon';
+import { useMemo } from 'react';
+import { useLocation, useNavigate, useSearchParams } from 'react-router';
+import { UAParser } from 'ua-parser-js';
const dateFormat: DateTimeFormatOptions = {
...DateTime.DATETIME_SHORT,
diff --git a/apps/remix/app/components/tables/settings-security-passkey-table-actions.tsx b/apps/remix/app/components/tables/settings-security-passkey-table-actions.tsx
index c14ae8036..7feb0e191 100644
--- a/apps/remix/app/components/tables/settings-security-passkey-table-actions.tsx
+++ b/apps/remix/app/components/tables/settings-security-passkey-table-actions.tsx
@@ -1,12 +1,3 @@
-import { useState } from 'react';
-
-import { zodResolver } from '@hookform/resolvers/zod';
-import { msg } from '@lingui/core/macro';
-import { useLingui } from '@lingui/react';
-import { Trans } from '@lingui/react/macro';
-import { useForm } from 'react-hook-form';
-import { z } from 'zod';
-
import { trpc } from '@documenso/trpc/react';
import { cn } from '@documenso/ui/lib/utils';
import { Button } from '@documenso/ui/primitives/button';
@@ -20,16 +11,16 @@ import {
DialogTitle,
DialogTrigger,
} from '@documenso/ui/primitives/dialog';
-import {
- Form,
- FormControl,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
-} from '@documenso/ui/primitives/form/form';
+import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@documenso/ui/primitives/form/form';
import { Input } from '@documenso/ui/primitives/input';
import { useToast } from '@documenso/ui/primitives/use-toast';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { msg } from '@lingui/core/macro';
+import { useLingui } from '@lingui/react';
+import { Trans } from '@lingui/react/macro';
+import { useState } from 'react';
+import { useForm } from 'react-hook-form';
+import { z } from 'zod';
export type SettingsSecurityPasskeyTableActionsProps = {
className?: string;
@@ -61,56 +52,47 @@ export const SettingsSecurityPasskeyTableActions = ({
},
});
- const { mutateAsync: updatePasskey, isPending: isUpdatingPasskey } =
- trpc.auth.passkey.update.useMutation({
- onSuccess: () => {
- toast({
- title: _(msg`Success`),
- description: _(msg`Passkey has been updated`),
- });
+ const { mutateAsync: updatePasskey, isPending: isUpdatingPasskey } = trpc.auth.passkey.update.useMutation({
+ onSuccess: () => {
+ toast({
+ title: _(msg`Success`),
+ description: _(msg`Passkey has been updated`),
+ });
- setIsUpdateDialogOpen(false);
- },
- onError: () => {
- toast({
- title: _(msg`Something went wrong`),
- description: _(
- msg`We are unable to update this passkey at the moment. Please try again later.`,
- ),
- duration: 10000,
- variant: 'destructive',
- });
- },
- });
+ setIsUpdateDialogOpen(false);
+ },
+ onError: () => {
+ toast({
+ title: _(msg`Something went wrong`),
+ description: _(msg`We are unable to update this passkey at the moment. Please try again later.`),
+ duration: 10000,
+ variant: 'destructive',
+ });
+ },
+ });
- const { mutateAsync: deletePasskey, isPending: isDeletingPasskey } =
- trpc.auth.passkey.delete.useMutation({
- onSuccess: () => {
- toast({
- title: _(msg`Success`),
- description: _(msg`Passkey has been removed`),
- });
+ const { mutateAsync: deletePasskey, isPending: isDeletingPasskey } = trpc.auth.passkey.delete.useMutation({
+ onSuccess: () => {
+ toast({
+ title: _(msg`Success`),
+ description: _(msg`Passkey has been removed`),
+ });
- setIsDeleteDialogOpen(false);
- },
- onError: () => {
- toast({
- title: _(msg`Something went wrong`),
- description: _(
- msg`We are unable to remove this passkey at the moment. Please try again later.`,
- ),
- duration: 10000,
- variant: 'destructive',
- });
- },
- });
+ setIsDeleteDialogOpen(false);
+ },
+ onError: () => {
+ toast({
+ title: _(msg`Something went wrong`),
+ description: _(msg`We are unable to remove this passkey at the moment. Please try again later.`),
+ duration: 10000,
+ variant: 'destructive',
+ });
+ },
+ });
return (
-
!isUpdatingPasskey && setIsUpdateDialogOpen(value)}
- >
+ !isUpdatingPasskey && setIsUpdateDialogOpen(value)}>
e.stopPropagation()} asChild>
Edit
@@ -173,10 +155,7 @@ export const SettingsSecurityPasskeyTableActions = ({
- !isDeletingPasskey && setIsDeleteDialogOpen(value)}
- >
+ !isDeletingPasskey && setIsDeleteDialogOpen(value)}>
e.stopPropagation()} asChild={true}>
Delete
diff --git a/apps/remix/app/components/tables/settings-security-passkey-table.tsx b/apps/remix/app/components/tables/settings-security-passkey-table.tsx
index b2fe09621..33b566956 100644
--- a/apps/remix/app/components/tables/settings-security-passkey-table.tsx
+++ b/apps/remix/app/components/tables/settings-security-passkey-table.tsx
@@ -1,10 +1,3 @@
-import { useMemo } from 'react';
-
-import { msg } from '@lingui/core/macro';
-import { useLingui } from '@lingui/react';
-import { DateTime } from 'luxon';
-import { useLocation, useNavigate, useSearchParams } from 'react-router';
-
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params';
import { trpc } from '@documenso/trpc/react';
@@ -13,6 +6,11 @@ import { DataTable } from '@documenso/ui/primitives/data-table';
import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination';
import { Skeleton } from '@documenso/ui/primitives/skeleton';
import { TableCell } from '@documenso/ui/primitives/table';
+import { msg } from '@lingui/core/macro';
+import { useLingui } from '@lingui/react';
+import { DateTime } from 'luxon';
+import { useMemo } from 'react';
+import { useLocation, useNavigate, useSearchParams } from 'react-router';
import { SettingsSecurityPasskeyTableActions } from './settings-security-passkey-table-actions';
@@ -66,9 +64,7 @@ export const SettingsSecurityPasskeyTable = () => {
header: _(msg`Last used`),
accessorKey: 'updatedAt',
cell: ({ row }) =>
- row.original.lastUsedAt
- ? DateTime.fromJSDate(row.original.lastUsedAt).toRelative()
- : _(msg`Never`),
+ row.original.lastUsedAt ? DateTime.fromJSDate(row.original.lastUsedAt).toRelative() : _(msg`Never`),
},
{
id: 'actions',
diff --git a/apps/remix/app/components/tables/team-groups-table.tsx b/apps/remix/app/components/tables/team-groups-table.tsx
index 3bbf072b4..4ad463cbf 100644
--- a/apps/remix/app/components/tables/team-groups-table.tsx
+++ b/apps/remix/app/components/tables/team-groups-table.tsx
@@ -1,12 +1,3 @@
-import { useMemo } from 'react';
-
-import { msg } from '@lingui/core/macro';
-import { useLingui } from '@lingui/react';
-import { Trans } from '@lingui/react/macro';
-import { OrganisationGroupType } from '@prisma/client';
-import { EditIcon, MoreHorizontalIcon, Trash2Icon } from 'lucide-react';
-import { useSearchParams } from 'react-router';
-
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { EXTENDED_TEAM_MEMBER_ROLE_MAP } from '@documenso/lib/constants/teams-translations';
import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params';
@@ -23,6 +14,13 @@ import {
} from '@documenso/ui/primitives/dropdown-menu';
import { Skeleton } from '@documenso/ui/primitives/skeleton';
import { TableCell } from '@documenso/ui/primitives/table';
+import { msg } from '@lingui/core/macro';
+import { useLingui } from '@lingui/react';
+import { Trans } from '@lingui/react/macro';
+import { OrganisationGroupType } from '@prisma/client';
+import { EditIcon, MoreHorizontalIcon, Trash2Icon } from 'lucide-react';
+import { useMemo } from 'react';
+import { useSearchParams } from 'react-router';
import { useCurrentTeam } from '~/providers/team';
@@ -86,7 +84,7 @@ export const TeamGroupsTable = () => {
cell: ({ row }) => (
-
+
@@ -99,10 +97,7 @@ export const TeamGroupsTable = () => {
teamGroupName={row.original.name ?? ''}
teamGroupRole={row.original.teamRole}
trigger={
- e.preventDefault()}
- title="Update team group role"
- >
+ e.preventDefault()} title="Update team group role">
Update role
@@ -139,7 +134,7 @@ export const TeamGroupsTable = () => {
enable: isLoadingError,
}}
emptyState={
-
+
No team groups found
@@ -173,11 +168,7 @@ export const TeamGroupsTable = () => {
),
}}
>
- {(table) =>
- results.totalPages > 1 && (
-
- )
- }
+ {(table) => results.totalPages > 1 &&
}
);
};
diff --git a/apps/remix/app/components/tables/team-members-table.tsx b/apps/remix/app/components/tables/team-members-table.tsx
index 02771c322..c8a9f0faa 100644
--- a/apps/remix/app/components/tables/team-members-table.tsx
+++ b/apps/remix/app/components/tables/team-members-table.tsx
@@ -1,12 +1,3 @@
-import { useMemo } from 'react';
-
-import { msg } from '@lingui/core/macro';
-import { useLingui } from '@lingui/react';
-import { Trans } from '@lingui/react/macro';
-import { OrganisationGroupType, OrganisationMemberRole } from '@prisma/client';
-import { EditIcon, MoreHorizontal, Trash2Icon } from 'lucide-react';
-import { useSearchParams } from 'react-router';
-
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation';
import { EXTENDED_TEAM_MEMBER_ROLE_MAP } from '@documenso/lib/constants/teams-translations';
@@ -28,6 +19,13 @@ import {
} from '@documenso/ui/primitives/dropdown-menu';
import { Skeleton } from '@documenso/ui/primitives/skeleton';
import { TableCell } from '@documenso/ui/primitives/table';
+import { msg } from '@lingui/core/macro';
+import { useLingui } from '@lingui/react';
+import { Trans } from '@lingui/react/macro';
+import { OrganisationGroupType, OrganisationMemberRole } from '@prisma/client';
+import { EditIcon, MoreHorizontal, Trash2Icon } from 'lucide-react';
+import { useMemo } from 'react';
+import { useSearchParams } from 'react-router';
import { useCurrentTeam } from '~/providers/team';
@@ -100,9 +98,7 @@ export const TeamMembersTable = () => {
{row.original.name}
- }
+ primaryText={{row.original.name} }
secondaryText={row.original.email}
/>
);
@@ -130,7 +126,7 @@ export const TeamMembersTable = () => {
cell: ({ row }) => (
-
+
@@ -231,9 +227,7 @@ export const TeamMembersTable = () => {
- {!groupQuery.isPending && (
-
- )}
+ {!groupQuery.isPending && }
);
diff --git a/apps/remix/app/components/tables/templates-table-action-dropdown.tsx b/apps/remix/app/components/tables/templates-table-action-dropdown.tsx
index 05b6a08fe..8872a1a78 100644
--- a/apps/remix/app/components/tables/templates-table-action-dropdown.tsx
+++ b/apps/remix/app/components/tables/templates-table-action-dropdown.tsx
@@ -1,20 +1,3 @@
-import { useState } from 'react';
-
-import { Trans } from '@lingui/react/macro';
-import { DocumentStatus, EnvelopeType, type TemplateDirectLink } from '@prisma/client';
-import {
- Copy,
- Download,
- Edit,
- FolderIcon,
- MoreHorizontal,
- Pencil,
- Share2Icon,
- Trash2,
- Upload,
-} from 'lucide-react';
-import { Link } from 'react-router';
-
import type { TRecipientLite } from '@documenso/lib/types/recipient';
import { trpc as trpcReact } from '@documenso/trpc/react';
import {
@@ -24,6 +7,11 @@ import {
DropdownMenuLabel,
DropdownMenuTrigger,
} from '@documenso/ui/primitives/dropdown-menu';
+import { Trans } from '@lingui/react/macro';
+import { DocumentStatus, EnvelopeType, type TemplateDirectLink } from '@prisma/client';
+import { Copy, Download, Edit, FolderIcon, MoreHorizontal, Pencil, Share2Icon, Trash2, Upload } from 'lucide-react';
+import { useState } from 'react';
+import { Link } from 'react-router';
import { EnvelopeDeleteDialog } from '../dialogs/envelope-delete-dialog';
import { EnvelopeDownloadDialog } from '../dialogs/envelope-download-dialog';
diff --git a/apps/remix/app/components/tables/templates-table.tsx b/apps/remix/app/components/tables/templates-table.tsx
index 46240d4ca..cc7754ffd 100644
--- a/apps/remix/app/components/tables/templates-table.tsx
+++ b/apps/remix/app/components/tables/templates-table.tsx
@@ -1,19 +1,3 @@
-import { useMemo, useTransition } from 'react';
-
-import { msg } from '@lingui/core/macro';
-import { useLingui } from '@lingui/react';
-import { Trans } from '@lingui/react/macro';
-import {
- AlertTriangle,
- Building2Icon,
- Globe2Icon,
- InfoIcon,
- Link2Icon,
- Loader,
- LockIcon,
-} from 'lucide-react';
-import { Link } from 'react-router';
-
import { useLimits } from '@documenso/ee/server-only/limits/provider/client';
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation';
@@ -27,6 +11,12 @@ import { DataTablePagination } from '@documenso/ui/primitives/data-table-paginat
import { Skeleton } from '@documenso/ui/primitives/skeleton';
import { TableCell } from '@documenso/ui/primitives/table';
import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip';
+import { msg } from '@lingui/core/macro';
+import { useLingui } from '@lingui/react';
+import { Trans } from '@lingui/react/macro';
+import { AlertTriangle, Building2Icon, Globe2Icon, InfoIcon, Link2Icon, Loader, LockIcon } from 'lucide-react';
+import { useMemo, useTransition } from 'react';
+import { Link } from 'react-router';
import { TemplateType } from '~/components/general/template/template-type';
import { useCurrentTeam } from '~/providers/team';
@@ -128,7 +118,7 @@ export const TemplatesTable = ({
-
+
@@ -138,8 +128,8 @@ export const TemplatesTable = ({
- Public templates are connected to your public profile. Any modifications to
- public templates will also appear in your public profile.
+ Public templates are connected to your public profile. Any modifications to public templates
+ will also appear in your public profile.
@@ -151,9 +141,8 @@ export const TemplatesTable = ({
- Direct link templates contain one dynamic recipient placeholder. Anyone with
- access to this link can sign the document, and it will then appear on your
- documents page.
+ Direct link templates contain one dynamic recipient placeholder. Anyone with access to this link
+ can sign the document, and it will then appear on your documents page.
@@ -165,10 +154,7 @@ export const TemplatesTable = ({
{team?.id ? (
-
- Team only templates are not linked anywhere and are visible only to your
- team.
-
+ Team only templates are not linked anywhere and are visible only to your team.
) : (
Private templates can only be modified and viewed by you.
)}
@@ -182,8 +168,8 @@ export const TemplatesTable = ({
- Organisation templates are shared across all teams within the same
- organisation. Only the owning team can edit them.
+ Organisation templates are shared across all teams within the same organisation. Only the owning
+ team can edit them.
@@ -201,9 +187,7 @@ export const TemplatesTable = ({
{isFromOtherTeam && row.original.team?.name && (
-
- ({row.original.team.name})
-
+ ({row.original.team.name})
)}
{row.original.directLink?.token && (
@@ -232,11 +216,7 @@ export const TemplatesTable = ({
documentRootPath={documentRootPath}
/>
-
+
);
},
@@ -273,10 +253,7 @@ export const TemplatesTable = ({
You have reached your document limit.{' '}
-
+
Upgrade your account to continue!
diff --git a/apps/remix/app/components/tables/user-billing-organisations-table.tsx b/apps/remix/app/components/tables/user-billing-organisations-table.tsx
index bc6a2c604..9cf3aebfc 100644
--- a/apps/remix/app/components/tables/user-billing-organisations-table.tsx
+++ b/apps/remix/app/components/tables/user-billing-organisations-table.tsx
@@ -1,10 +1,3 @@
-import { useMemo } from 'react';
-
-import { Trans, useLingui } from '@lingui/react/macro';
-import { SubscriptionStatus } from '@prisma/client';
-import { Link } from 'react-router';
-import { match } from 'ts-pattern';
-
import { useSession } from '@documenso/lib/client-only/providers/session';
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
import { formatAvatarUrl } from '@documenso/lib/utils/avatars';
@@ -14,15 +7,18 @@ import { Badge } from '@documenso/ui/primitives/badge';
import { Button } from '@documenso/ui/primitives/button';
import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table';
import { DataTable } from '@documenso/ui/primitives/data-table';
+import { Trans, useLingui } from '@lingui/react/macro';
+import { SubscriptionStatus } from '@prisma/client';
+import { useMemo } from 'react';
+import { Link } from 'react-router';
+import { match } from 'ts-pattern';
export const UserBillingOrganisationsTable = () => {
const { t } = useLingui();
const { organisations } = useSession();
const billingOrganisations = useMemo(() => {
- return organisations.filter((org) =>
- canExecuteOrganisationAction('MANAGE_BILLING', org.currentOrganisationRole),
- );
+ return organisations.filter((org) => canExecuteOrganisationAction('MANAGE_BILLING', org.currentOrganisationRole));
}, [organisations]);
const getSubscriptionStatusDisplay = (status: SubscriptionStatus | undefined) => {
@@ -56,9 +52,7 @@ export const UserBillingOrganisationsTable = () => {
avatarSrc={formatAvatarUrl(row.original.avatarImageId)}
avatarClass="h-12 w-12"
avatarFallback={row.original.name.slice(0, 1).toUpperCase()}
- primaryText={
- {row.original.name}
- }
+ primaryText={{row.original.name} }
secondaryText={`${NEXT_PUBLIC_WEBAPP_URL()}/o/${row.original.url}`}
/>
@@ -91,7 +85,7 @@ export const UserBillingOrganisationsTable = () => {
if (billingOrganisations.length === 0) {
return (
-
+
You don't manage billing for any organisations.
diff --git a/apps/remix/app/components/tables/user-organisations-table.tsx b/apps/remix/app/components/tables/user-organisations-table.tsx
index 6bfdedadc..ca1131a81 100644
--- a/apps/remix/app/components/tables/user-organisations-table.tsx
+++ b/apps/remix/app/components/tables/user-organisations-table.tsx
@@ -1,10 +1,3 @@
-import { useMemo } from 'react';
-
-import { msg } from '@lingui/core/macro';
-import { useLingui } from '@lingui/react';
-import { Trans } from '@lingui/react/macro';
-import { Link } from 'react-router';
-
import { useSession } from '@documenso/lib/client-only/providers/session';
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
import { ORGANISATION_MEMBER_ROLE_MAP } from '@documenso/lib/constants/organisations-translations';
@@ -17,6 +10,11 @@ import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table';
import { DataTable } from '@documenso/ui/primitives/data-table';
import { Skeleton } from '@documenso/ui/primitives/skeleton';
import { TableCell } from '@documenso/ui/primitives/table';
+import { msg } from '@lingui/core/macro';
+import { useLingui } from '@lingui/react';
+import { Trans } from '@lingui/react/macro';
+import { useMemo } from 'react';
+import { Link } from 'react-router';
import { OrganisationLeaveDialog } from '../dialogs/organisation-leave-dialog';
@@ -55,7 +53,7 @@ export const UserOrganisationsTable = () => {
avatarClass="h-12 w-12"
avatarFallback={row.original.name.slice(0, 1).toUpperCase()}
primaryText={
-
+
{isPersonalLayoutMode
? _(
msg({
@@ -92,10 +90,7 @@ export const UserOrganisationsTable = () => {
id: 'actions',
cell: ({ row }) => (
- {canExecuteOrganisationAction(
- 'MANAGE_ORGANISATION',
- row.original.currentOrganisationRole,
- ) && (
+ {canExecuteOrganisationAction('MANAGE_ORGANISATION', row.original.currentOrganisationRole) && (
Manage
diff --git a/apps/remix/app/entry.client.tsx b/apps/remix/app/entry.client.tsx
index c32cdc4e1..86e949d7a 100644
--- a/apps/remix/app/entry.client.tsx
+++ b/apps/remix/app/entry.client.tsx
@@ -1,15 +1,12 @@
-import { StrictMode, startTransition, useEffect } from 'react';
-
+import { extractPostHogConfig } from '@documenso/lib/constants/feature-flags';
+import { dynamicActivate } from '@documenso/lib/utils/i18n';
import { i18n } from '@lingui/core';
import { detect, fromHtmlTag } from '@lingui/detect-locale';
import { I18nProvider } from '@lingui/react';
-import posthog from 'posthog-js';
+import { StrictMode, startTransition, useEffect } from 'react';
import { hydrateRoot } from 'react-dom/client';
import { HydratedRouter } from 'react-router/dom';
-import { extractPostHogConfig } from '@documenso/lib/constants/feature-flags';
-import { dynamicActivate } from '@documenso/lib/utils/i18n';
-
import './utils/polyfills/promise-with-resolvers';
function PosthogInit() {
@@ -17,9 +14,11 @@ function PosthogInit() {
useEffect(() => {
if (postHogConfig) {
- posthog.init(postHogConfig.key, {
- api_host: postHogConfig.host,
- capture_exceptions: true,
+ void import('posthog-js').then(({ default: posthog }) => {
+ posthog.init(postHogConfig.key, {
+ api_host: postHogConfig.host,
+ capture_exceptions: true,
+ });
});
}
}, []);
diff --git a/apps/remix/app/entry.server.tsx b/apps/remix/app/entry.server.tsx
index d38ef3dea..7f28001f4 100644
--- a/apps/remix/app/entry.server.tsx
+++ b/apps/remix/app/entry.server.tsx
@@ -1,16 +1,15 @@
+import { PassThrough } from 'node:stream';
+import { APP_I18N_OPTIONS } from '@documenso/lib/constants/i18n';
+import { dynamicActivate, extractLocaleData } from '@documenso/lib/utils/i18n';
import { i18n } from '@lingui/core';
import { I18nProvider } from '@lingui/react';
import { createReadableStreamFromReadable } from '@react-router/node';
import { isbot } from 'isbot';
-import { PassThrough } from 'node:stream';
import type { RenderToPipeableStreamOptions } from 'react-dom/server';
import { renderToPipeableStream } from 'react-dom/server';
import type { AppLoadContext, EntryContext } from 'react-router';
import { ServerRouter } from 'react-router';
-import { APP_I18N_OPTIONS } from '@documenso/lib/constants/i18n';
-import { dynamicActivate, extractLocaleData } from '@documenso/lib/utils/i18n';
-
import { langCookie } from './storage/lang-cookie.server';
export const streamTimeout = 5_000;
diff --git a/apps/remix/app/providers/team.tsx b/apps/remix/app/providers/team.tsx
index d77c77428..7f309fdbd 100644
--- a/apps/remix/app/providers/team.tsx
+++ b/apps/remix/app/providers/team.tsx
@@ -1,7 +1,6 @@
-import { createContext, useContext } from 'react';
-import React from 'react';
-
import type { TeamSession } from '@documenso/trpc/server/organisation-router/get-organisation-session.types';
+import type React from 'react';
+import { createContext, useContext } from 'react';
type TeamProviderValue = TeamSession;
diff --git a/apps/remix/app/root.tsx b/apps/remix/app/root.tsx
index 9fbcecb86..096b1504e 100644
--- a/apps/remix/app/root.tsx
+++ b/apps/remix/app/root.tsx
@@ -1,16 +1,3 @@
-import { NuqsAdapter } from 'nuqs/adapters/react-router/v7';
-import {
- Links,
- Meta,
- Outlet,
- Scripts,
- ScrollRestoration,
- data,
- isRouteErrorResponse,
- useLoaderData,
-} from 'react-router';
-import { PreventFlashOnWrongTheme, ThemeProvider, useTheme } from 'remix-themes';
-
import { getOptionalSession } from '@documenso/auth/server/lib/utils/get-session';
import { SessionProvider } from '@documenso/lib/client-only/providers/session';
import { APP_I18N_OPTIONS, type SupportedLanguageCodes } from '@documenso/lib/constants/i18n';
@@ -20,6 +7,19 @@ import { TrpcProvider } from '@documenso/trpc/react';
import { getOrganisationSession } from '@documenso/trpc/server/organisation-router/get-organisation-session';
import { Toaster } from '@documenso/ui/primitives/toaster';
import { TooltipProvider } from '@documenso/ui/primitives/tooltip';
+import { NuqsAdapter } from 'nuqs/adapters/react-router/v7';
+import {
+ data,
+ isRouteErrorResponse,
+ Links,
+ Meta,
+ Outlet,
+ Scripts,
+ ScrollRestoration,
+ useLoaderData,
+ useMatches,
+} from 'react-router';
+import { PreventFlashOnWrongTheme, ThemeProvider, useTheme } from 'remix-themes';
import type { Route } from './+types/root';
import stylesheet from './app.css?url';
@@ -111,6 +111,13 @@ export function LayoutContent({ children }: { children: React.ReactNode }) {
const [theme] = useTheme();
+ // Recipient routes (signing pages) put `documenso-branded` on so the
+ // inside a string value', () => {
+ const result = sanitizeBrandingCss('.x { font-family: " "; }');
+
+ expect(result.css.toLowerCase()).not.toContain(' inside a CSS comment', () => {
+ const result = sanitizeBrandingCss('.x { color: red; /* */ }');
+
+ expect(result.css.toLowerCase()).not.toContain(' inside an at-rule params block', () => {
+ const result = sanitizeBrandingCss(
+ '@media screen and (foo: bar) { .x { color: red; } }',
+ );
+
+ expect(result.css.toLowerCase()).not.toContain(' in a value', () => {
+ const result = sanitizeBrandingCss('.x { font-family: "foo"; }');
+
+ expect(result.css.toLowerCase()).not.toContain(' in an attribute selector value', () => {
+ const result = sanitizeBrandingCss('[data-x=""] { color: red; }');
+
+ expect(result.css.toLowerCase()).not.toContain(' {
+ // `"; }');
+
+ // The output keeps the literal `` end tag's `<` for the same reason it'd escape ``.
+ expect(result.css).toContain('