mirror of
https://github.com/documenso/documenso.git
synced 2026-07-24 17:04:12 +10:00
fix: lint project (#2693)
This commit is contained in:
@@ -6,11 +6,7 @@ type AnimateGenericFadeInOutProps = {
|
||||
motionKey?: string;
|
||||
};
|
||||
|
||||
export const AnimateGenericFadeInOut = ({
|
||||
children,
|
||||
className,
|
||||
motionKey,
|
||||
}: AnimateGenericFadeInOutProps) => {
|
||||
export const AnimateGenericFadeInOut = ({ children, className, motionKey }: AnimateGenericFadeInOutProps) => {
|
||||
return (
|
||||
<motion.section
|
||||
key={motionKey}
|
||||
|
||||
@@ -6,5 +6,5 @@ type ClientOnlyProps = {
|
||||
};
|
||||
|
||||
export const ClientOnly = ({ children, fallback = null }: ClientOnlyProps) => {
|
||||
return useHydrated() ? <>{children()}</> : <>{fallback}</>;
|
||||
return useHydrated() ? children() : fallback;
|
||||
};
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import { CheckSquareIcon, CopyIcon } from 'lucide-react';
|
||||
|
||||
import { useCopyToClipboard } from '@documenso/lib/client-only/hooks/use-copy-to-clipboard';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { CheckSquareIcon, CopyIcon } from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { cn } from '../../lib/utils';
|
||||
|
||||
@@ -66,11 +63,7 @@ export const CopyTextButton = ({
|
||||
)}
|
||||
>
|
||||
<div className="absolute">
|
||||
{copiedTimeout ? (
|
||||
<CheckSquareIcon className="h-3.5 w-3.5" />
|
||||
) : (
|
||||
<CopyIcon className="h-3.5 w-3.5" />
|
||||
)}
|
||||
{copiedTimeout ? <CheckSquareIcon className="h-3.5 w-3.5" /> : <CopyIcon className="h-3.5 w-3.5" />}
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { CheckIcon } from 'lucide-react';
|
||||
|
||||
import { SUPPORTED_LANGUAGES } from '@documenso/lib/constants/i18n';
|
||||
import { dynamicActivate } from '@documenso/lib/utils/i18n';
|
||||
import { cn } from '@documenso/ui/lib/utils';
|
||||
import {
|
||||
CommandDialog,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from '@documenso/ui/primitives/command';
|
||||
import { CommandDialog, CommandGroup, CommandInput, CommandItem, CommandList } from '@documenso/ui/primitives/command';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { CheckIcon } from 'lucide-react';
|
||||
|
||||
type LanguageSwitcherDialogProps = {
|
||||
open: boolean;
|
||||
@@ -48,12 +41,7 @@ export const LanguageSwitcherDialog = ({ open, setOpen }: LanguageSwitcherDialog
|
||||
value={_(language.full)}
|
||||
onSelect={async () => setLanguage(language.short)}
|
||||
>
|
||||
<CheckIcon
|
||||
className={cn(
|
||||
'mr-2 h-4 w-4',
|
||||
i18n.locale === language.short ? 'opacity-100' : 'opacity-0',
|
||||
)}
|
||||
/>
|
||||
<CheckIcon className={cn('mr-2 h-4 w-4', i18n.locale === language.short ? 'opacity-100' : 'opacity-0')} />
|
||||
{_(language.full)}
|
||||
</CommandItem>
|
||||
))}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useCallback, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { CheckIcon, CopyIcon } from 'lucide-react';
|
||||
import { DateTime } from 'luxon';
|
||||
import { useCallback, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { cn } from '../../lib/utils';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '../../primitives/popover';
|
||||
@@ -86,12 +85,7 @@ export const LocalTime = ({ date, className }: LocalTimeProps) => {
|
||||
isCopied={copiedField === 'Local'}
|
||||
onCopy={() => void onCopy('Local', local)}
|
||||
/>
|
||||
<TimeRow
|
||||
label="UTC"
|
||||
value={utc}
|
||||
isCopied={copiedField === 'UTC'}
|
||||
onCopy={() => void onCopy('UTC', utc)}
|
||||
/>
|
||||
<TimeRow label="UTC" value={utc} isCopied={copiedField === 'UTC'} onCopy={() => void onCopy('UTC', utc)} />
|
||||
<TimeRow
|
||||
label="Unix"
|
||||
value={unix}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { InfoIcon } from 'lucide-react';
|
||||
|
||||
import type { TDocumentEmailSettings } from '@documenso/lib/types/document-email';
|
||||
import { DocumentEmailEvents } from '@documenso/lib/types/document-email';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { InfoIcon } from 'lucide-react';
|
||||
|
||||
import { cn } from '../../lib/utils';
|
||||
import { Checkbox } from '../../primitives/checkbox';
|
||||
@@ -16,11 +15,7 @@ type DocumentEmailCheckboxesProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const DocumentEmailCheckboxes = ({
|
||||
value,
|
||||
onChange,
|
||||
className,
|
||||
}: DocumentEmailCheckboxesProps) => {
|
||||
export const DocumentEmailCheckboxes = ({ value, onChange, className }: DocumentEmailCheckboxesProps) => {
|
||||
return (
|
||||
<div className={cn('space-y-3', className)}>
|
||||
<div className="flex flex-row items-center">
|
||||
@@ -28,13 +23,11 @@ export const DocumentEmailCheckboxes = ({
|
||||
id={DocumentEmailEvents.RecipientSigned}
|
||||
className="h-5 w-5"
|
||||
checked={value.recipientSigned}
|
||||
onCheckedChange={(checked) =>
|
||||
onChange({ ...value, [DocumentEmailEvents.RecipientSigned]: Boolean(checked) })
|
||||
}
|
||||
onCheckedChange={(checked) => onChange({ ...value, [DocumentEmailEvents.RecipientSigned]: Boolean(checked) })}
|
||||
/>
|
||||
|
||||
<label
|
||||
className="ml-2 flex flex-row items-center text-sm text-muted-foreground"
|
||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||
htmlFor={DocumentEmailEvents.RecipientSigned}
|
||||
>
|
||||
<Trans>Email the owner when a recipient signs</Trans>
|
||||
@@ -52,9 +45,7 @@ export const DocumentEmailCheckboxes = ({
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<Trans>
|
||||
This email is sent to the document owner when a recipient has signed the document.
|
||||
</Trans>
|
||||
<Trans>This email is sent to the document owner when a recipient has signed the document.</Trans>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
@@ -72,7 +63,7 @@ export const DocumentEmailCheckboxes = ({
|
||||
/>
|
||||
|
||||
<label
|
||||
className="ml-2 flex flex-row items-center text-sm text-muted-foreground"
|
||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||
htmlFor={DocumentEmailEvents.RecipientSigningRequest}
|
||||
>
|
||||
<Trans>Email recipients with a signing request</Trans>
|
||||
@@ -90,9 +81,7 @@ export const DocumentEmailCheckboxes = ({
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<Trans>
|
||||
This email is sent to the recipient requesting them to sign the document.
|
||||
</Trans>
|
||||
<Trans>This email is sent to the recipient requesting them to sign the document.</Trans>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
@@ -110,7 +99,7 @@ export const DocumentEmailCheckboxes = ({
|
||||
/>
|
||||
|
||||
<label
|
||||
className="ml-2 flex flex-row items-center text-sm text-muted-foreground"
|
||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||
htmlFor={DocumentEmailEvents.RecipientRemoved}
|
||||
>
|
||||
<Trans>Email recipients when they're removed from a pending document</Trans>
|
||||
@@ -128,9 +117,7 @@ export const DocumentEmailCheckboxes = ({
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<Trans>
|
||||
This email is sent to the recipient if they are removed from a pending document.
|
||||
</Trans>
|
||||
<Trans>This email is sent to the recipient if they are removed from a pending document.</Trans>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
@@ -142,13 +129,11 @@ export const DocumentEmailCheckboxes = ({
|
||||
id={DocumentEmailEvents.DocumentPending}
|
||||
className="h-5 w-5"
|
||||
checked={value.documentPending}
|
||||
onCheckedChange={(checked) =>
|
||||
onChange({ ...value, [DocumentEmailEvents.DocumentPending]: Boolean(checked) })
|
||||
}
|
||||
onCheckedChange={(checked) => onChange({ ...value, [DocumentEmailEvents.DocumentPending]: Boolean(checked) })}
|
||||
/>
|
||||
|
||||
<label
|
||||
className="ml-2 flex flex-row items-center text-sm text-muted-foreground"
|
||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||
htmlFor={DocumentEmailEvents.DocumentPending}
|
||||
>
|
||||
<Trans>Email the signer if the document is still pending</Trans>
|
||||
@@ -167,8 +152,8 @@ export const DocumentEmailCheckboxes = ({
|
||||
|
||||
<p>
|
||||
<Trans>
|
||||
This email will be sent to the recipient who has just signed the document, if
|
||||
there are still other recipients who have not signed yet.
|
||||
This email will be sent to the recipient who has just signed the document, if there are still other
|
||||
recipients who have not signed yet.
|
||||
</Trans>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
@@ -187,7 +172,7 @@ export const DocumentEmailCheckboxes = ({
|
||||
/>
|
||||
|
||||
<label
|
||||
className="ml-2 flex flex-row items-center text-sm text-muted-foreground"
|
||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||
htmlFor={DocumentEmailEvents.DocumentCompleted}
|
||||
>
|
||||
<Trans>Email recipients when the document is completed</Trans>
|
||||
@@ -205,9 +190,7 @@ export const DocumentEmailCheckboxes = ({
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<Trans>
|
||||
This will be sent to all recipients once the document has been fully completed.
|
||||
</Trans>
|
||||
<Trans>This will be sent to all recipients once the document has been fully completed.</Trans>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
@@ -219,13 +202,11 @@ export const DocumentEmailCheckboxes = ({
|
||||
id={DocumentEmailEvents.DocumentDeleted}
|
||||
className="h-5 w-5"
|
||||
checked={value.documentDeleted}
|
||||
onCheckedChange={(checked) =>
|
||||
onChange({ ...value, [DocumentEmailEvents.DocumentDeleted]: Boolean(checked) })
|
||||
}
|
||||
onCheckedChange={(checked) => onChange({ ...value, [DocumentEmailEvents.DocumentDeleted]: Boolean(checked) })}
|
||||
/>
|
||||
|
||||
<label
|
||||
className="ml-2 flex flex-row items-center text-sm text-muted-foreground"
|
||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||
htmlFor={DocumentEmailEvents.DocumentDeleted}
|
||||
>
|
||||
<Trans>Email recipients when a pending document is deleted</Trans>
|
||||
@@ -243,9 +224,7 @@ export const DocumentEmailCheckboxes = ({
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<Trans>
|
||||
This will be sent to all recipients if a pending document has been deleted.
|
||||
</Trans>
|
||||
<Trans>This will be sent to all recipients if a pending document has been deleted.</Trans>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
@@ -263,7 +242,7 @@ export const DocumentEmailCheckboxes = ({
|
||||
/>
|
||||
|
||||
<label
|
||||
className="ml-2 flex flex-row items-center text-sm text-muted-foreground"
|
||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||
htmlFor={DocumentEmailEvents.OwnerDocumentCompleted}
|
||||
>
|
||||
<Trans>Email the owner when the document is completed</Trans>
|
||||
@@ -281,10 +260,7 @@ export const DocumentEmailCheckboxes = ({
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<Trans>
|
||||
This will be sent to the document owner once the document has been fully
|
||||
completed.
|
||||
</Trans>
|
||||
<Trans>This will be sent to the document owner once the document has been fully completed.</Trans>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
@@ -302,7 +278,7 @@ export const DocumentEmailCheckboxes = ({
|
||||
/>
|
||||
|
||||
<label
|
||||
className="ml-2 flex flex-row items-center text-sm text-muted-foreground"
|
||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||
htmlFor={DocumentEmailEvents.OwnerDocumentCreated}
|
||||
>
|
||||
<Trans>Email the owner when a document is created from a direct template</Trans>
|
||||
@@ -321,8 +297,8 @@ export const DocumentEmailCheckboxes = ({
|
||||
|
||||
<p>
|
||||
<Trans>
|
||||
This email is sent to the document owner when a recipient creates a document via a
|
||||
direct template link.
|
||||
This email is sent to the document owner when a recipient creates a document via a direct template
|
||||
link.
|
||||
</Trans>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
@@ -341,7 +317,7 @@ export const DocumentEmailCheckboxes = ({
|
||||
/>
|
||||
|
||||
<label
|
||||
className="ml-2 flex flex-row items-center text-sm text-muted-foreground"
|
||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||
htmlFor={DocumentEmailEvents.OwnerRecipientExpired}
|
||||
>
|
||||
<Trans>Send recipient expired email to the owner</Trans>
|
||||
@@ -359,10 +335,7 @@ export const DocumentEmailCheckboxes = ({
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<Trans>
|
||||
This will be sent to the document owner when a recipient's signing window has
|
||||
expired.
|
||||
</Trans>
|
||||
<Trans>This will be sent to the document owner when a recipient's signing window has expired.</Trans>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import React from 'react';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { InfoIcon } from 'lucide-react';
|
||||
|
||||
import { DOCUMENT_AUTH_TYPES } from '@documenso/lib/constants/document-auth';
|
||||
import { DocumentAccessAuth } from '@documenso/lib/types/document-auth';
|
||||
import { MultiSelect, type Option } from '@documenso/ui/primitives/multiselect';
|
||||
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 { InfoIcon } from 'lucide-react';
|
||||
|
||||
export interface DocumentGlobalAuthAccessSelectProps {
|
||||
value?: string[];
|
||||
@@ -41,15 +38,11 @@ export const DocumentGlobalAuthAccessSelect = ({
|
||||
|
||||
// Convert string array to Option array for MultiSelect
|
||||
const selectedOptions =
|
||||
(value
|
||||
?.map((val) => authOptions.find((option) => option.value === val))
|
||||
.filter(Boolean) as Option[]) || [];
|
||||
(value?.map((val) => authOptions.find((option) => option.value === val)).filter(Boolean) as Option[]) || [];
|
||||
|
||||
// Convert default value to Option array
|
||||
const defaultOptions =
|
||||
(defaultValue
|
||||
?.map((val) => authOptions.find((option) => option.value === val))
|
||||
.filter(Boolean) as Option[]) || [];
|
||||
(defaultValue?.map((val) => authOptions.find((option) => option.value === val)).filter(Boolean) as Option[]) || [];
|
||||
|
||||
const handleChange = (options: Option[]) => {
|
||||
const values = options.map((option) => option.value);
|
||||
@@ -102,8 +95,7 @@ export const DocumentGlobalAuthAccessTooltip = () => (
|
||||
</li>
|
||||
<li>
|
||||
<Trans>
|
||||
<strong>No restrictions</strong> - The document can be accessed directly by the URL sent
|
||||
to the recipient
|
||||
<strong>No restrictions</strong> - The document can be accessed directly by the URL sent to the recipient
|
||||
</Trans>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { InfoIcon } from 'lucide-react';
|
||||
|
||||
import { DOCUMENT_AUTH_TYPES } from '@documenso/lib/constants/document-auth';
|
||||
import { DocumentActionAuth, DocumentAuth } from '@documenso/lib/types/document-auth';
|
||||
import { MultiSelect, type Option } from '@documenso/ui/primitives/multiselect';
|
||||
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 { InfoIcon } from 'lucide-react';
|
||||
|
||||
export interface DocumentGlobalAuthActionSelectProps {
|
||||
value?: string[];
|
||||
@@ -41,15 +40,11 @@ export const DocumentGlobalAuthActionSelect = ({
|
||||
|
||||
// Convert string array to Option array for MultiSelect
|
||||
const selectedOptions =
|
||||
(value
|
||||
?.map((val) => authOptions.find((option) => option.value === val))
|
||||
.filter(Boolean) as Option[]) || [];
|
||||
(value?.map((val) => authOptions.find((option) => option.value === val)).filter(Boolean) as Option[]) || [];
|
||||
|
||||
// Convert default value to Option array
|
||||
const defaultOptions =
|
||||
(defaultValue
|
||||
?.map((val) => authOptions.find((option) => option.value === val))
|
||||
.filter(Boolean) as Option[]) || [];
|
||||
(defaultValue?.map((val) => authOptions.find((option) => option.value === val)).filter(Boolean) as Option[]) || [];
|
||||
|
||||
const handleChange = (options: Option[]) => {
|
||||
const values = options.map((option) => option.value);
|
||||
@@ -85,36 +80,33 @@ export const DocumentGlobalAuthActionTooltip = () => (
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<Trans>
|
||||
The authentication methods required for recipients to sign the signature field.
|
||||
</Trans>
|
||||
<Trans>The authentication methods required for recipients to sign the signature field.</Trans>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<Trans>
|
||||
These can be overriden by setting the authentication requirements directly on each
|
||||
recipient in the next step. Multiple methods can be selected.
|
||||
These can be overriden by setting the authentication requirements directly on each recipient in the next step.
|
||||
Multiple methods can be selected.
|
||||
</Trans>
|
||||
</p>
|
||||
|
||||
<ul className="ml-3.5 list-outside list-disc space-y-0.5 py-2">
|
||||
<li>
|
||||
<Trans>
|
||||
<strong>Require passkey</strong> - The recipient must have an account and passkey
|
||||
configured via their settings
|
||||
<strong>Require passkey</strong> - The recipient must have an account and passkey configured via their
|
||||
settings
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<Trans>
|
||||
<strong>Require 2FA</strong> - The recipient must have an account and 2FA enabled via
|
||||
their settings
|
||||
<strong>Require 2FA</strong> - The recipient must have an account and 2FA enabled via their settings
|
||||
</Trans>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<Trans>
|
||||
<strong>Require password</strong> - The recipient must have an account and password
|
||||
configured via their settings, the password will be verified during signing
|
||||
<strong>Require password</strong> - The recipient must have an account and password configured via their
|
||||
settings, the password will be verified during signing
|
||||
</Trans>
|
||||
</li>
|
||||
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import type { DocumentMeta, Field } from '@prisma/client';
|
||||
import { SigningStatus } from '@prisma/client';
|
||||
import { Clock, EyeOffIcon } from 'lucide-react';
|
||||
|
||||
import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
|
||||
import { isTemplateRecipientEmailPlaceholder } from '@documenso/lib/constants/template';
|
||||
import type { TRecipientLite } from '@documenso/lib/types/recipient';
|
||||
@@ -18,6 +10,12 @@ import { Badge } from '@documenso/ui/primitives/badge';
|
||||
import { FRIENDLY_FIELD_TYPE } from '@documenso/ui/primitives/document-flow/types';
|
||||
import { ElementVisible } from '@documenso/ui/primitives/element-visible';
|
||||
import { PopoverHover } from '@documenso/ui/primitives/popover';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import type { DocumentMeta, Field } from '@prisma/client';
|
||||
import { SigningStatus } from '@prisma/client';
|
||||
import { Clock, EyeOffIcon } from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { getRecipientColorStyles } from '../../lib/recipient-colors';
|
||||
import { FieldContent } from '../../primitives/document-flow/field-content';
|
||||
@@ -67,10 +65,7 @@ export type DocumentReadOnlyFieldsProps = {
|
||||
showRecipientColors?: boolean;
|
||||
};
|
||||
|
||||
export const mapFieldsWithRecipients = (
|
||||
fields: Field[],
|
||||
recipients: TRecipientLite[],
|
||||
): DocumentField[] => {
|
||||
export const mapFieldsWithRecipients = (fields: Field[], recipients: TRecipientLite[]): DocumentField[] => {
|
||||
return fields.map((field) => {
|
||||
const recipient = recipients.find((recipient) => recipient.id === field.recipientId) || {
|
||||
id: field.recipientId,
|
||||
@@ -110,18 +105,16 @@ export const DocumentReadOnlyFields = ({
|
||||
readonly={true}
|
||||
color={
|
||||
showRecipientColors
|
||||
? getRecipientColorStyles(
|
||||
recipientIds.findIndex((id) => id === field.recipientId),
|
||||
)
|
||||
? getRecipientColorStyles(recipientIds.findIndex((id) => id === field.recipientId))
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{showRecipientTooltip && (
|
||||
<div className="absolute -right-3 -top-3">
|
||||
<div className="absolute -top-3 -right-3">
|
||||
<PopoverHover
|
||||
trigger={
|
||||
<Avatar className="h-6 w-6 border-2 border-solid border-gray-200/50 transition-colors hover:border-gray-200">
|
||||
<AvatarFallback className="bg-neutral-50 text-xs text-gray-400">
|
||||
<Avatar className="h-6 w-6 border-2 border-gray-200/50 border-solid transition-colors hover:border-gray-200">
|
||||
<AvatarFallback className="bg-neutral-50 text-gray-400 text-xs">
|
||||
{extractInitials(field.recipient.name || field.recipient.email)}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
@@ -133,11 +126,7 @@ export const DocumentReadOnlyFields = ({
|
||||
{showFieldStatus && (
|
||||
<Badge
|
||||
className="mx-auto mb-1 py-0.5"
|
||||
variant={
|
||||
field.recipient.signingStatus === SigningStatus.SIGNED
|
||||
? 'default'
|
||||
: 'secondary'
|
||||
}
|
||||
variant={field.recipient.signingStatus === SigningStatus.SIGNED ? 'default' : 'secondary'}
|
||||
>
|
||||
{field.recipient.signingStatus === SigningStatus.SIGNED ? (
|
||||
<>
|
||||
@@ -154,17 +143,15 @@ export const DocumentReadOnlyFields = ({
|
||||
)}
|
||||
|
||||
<p className="text-center font-semibold">
|
||||
<span>
|
||||
{parseMessageDescriptor(_, FRIENDLY_FIELD_TYPE[field.type])} field
|
||||
</span>
|
||||
<span>{parseMessageDescriptor(_, FRIENDLY_FIELD_TYPE[field.type])} field</span>
|
||||
</p>
|
||||
|
||||
<p className="mt-1 text-center text-xs text-muted-foreground">
|
||||
<p className="mt-1 text-center text-muted-foreground text-xs">
|
||||
{getRecipientDisplayText(field.recipient)}
|
||||
</p>
|
||||
|
||||
<button
|
||||
className="absolute right-0 top-0 my-1 p-2 focus:outline-none focus-visible:ring-0"
|
||||
className="absolute top-0 right-0 my-1 p-2 focus:outline-none focus-visible:ring-0"
|
||||
onClick={() => handleHideField(field.secondaryId)}
|
||||
title="Hide field"
|
||||
>
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
|
||||
export const DocumentSendEmailMessageHelper = () => {
|
||||
@@ -11,21 +9,15 @@ export const DocumentSendEmailMessageHelper = () => {
|
||||
|
||||
<ul className="mt-2 flex list-inside list-disc flex-col gap-y-2 text-sm">
|
||||
<li className="text-muted-foreground">
|
||||
<code className="text-muted-foreground bg-muted-foreground/20 rounded p-1 text-sm">
|
||||
{'{signer.name}'}
|
||||
</code>{' '}
|
||||
- <Trans>The signer's name</Trans>
|
||||
<code className="rounded bg-muted-foreground/20 p-1 text-muted-foreground text-sm">{'{signer.name}'}</code> -{' '}
|
||||
<Trans>The signer's name</Trans>
|
||||
</li>
|
||||
<li className="text-muted-foreground">
|
||||
<code className="text-muted-foreground bg-muted-foreground/20 rounded p-1 text-sm">
|
||||
{'{signer.email}'}
|
||||
</code>{' '}
|
||||
- <Trans>The signer's email</Trans>
|
||||
<code className="rounded bg-muted-foreground/20 p-1 text-muted-foreground text-sm">{'{signer.email}'}</code> -{' '}
|
||||
<Trans>The signer's email</Trans>
|
||||
</li>
|
||||
<li className="text-muted-foreground">
|
||||
<code className="text-muted-foreground bg-muted-foreground/20 rounded p-1 text-sm">
|
||||
{'{document.name}'}
|
||||
</code>{' '}
|
||||
<code className="rounded bg-muted-foreground/20 p-1 text-muted-foreground text-sm">{'{document.name}'}</code>{' '}
|
||||
- <Trans>The document's name</Trans>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import type { HTMLAttributes } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { Copy, Sparkles } from 'lucide-react';
|
||||
import { FaXTwitter } from 'react-icons/fa6';
|
||||
|
||||
import { useCopyShareLink } from '@documenso/lib/client-only/hooks/use-copy-share-link';
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
|
||||
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
|
||||
import { generateTwitterIntent } from '@documenso/lib/universal/generate-twitter-intent';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { Copy, Sparkles } from 'lucide-react';
|
||||
import type React from 'react';
|
||||
import type { HTMLAttributes } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { FaXTwitter } from 'react-icons/fa6';
|
||||
|
||||
import { cn } from '../../lib/utils';
|
||||
import { Button } from '../../primitives/button';
|
||||
@@ -31,12 +30,7 @@ export type DocumentShareButtonProps = HTMLAttributes<HTMLButtonElement> & {
|
||||
trigger?: (_props: { loading: boolean; disabled: boolean }) => React.ReactNode;
|
||||
};
|
||||
|
||||
export const DocumentShareButton = ({
|
||||
token,
|
||||
documentId,
|
||||
className,
|
||||
trigger,
|
||||
}: DocumentShareButtonProps) => {
|
||||
export const DocumentShareButton = ({ token, documentId, className, trigger }: DocumentShareButtonProps) => {
|
||||
const { _ } = useLingui();
|
||||
const { toast } = useToast();
|
||||
|
||||
@@ -147,9 +141,8 @@ export const DocumentShareButton = ({
|
||||
|
||||
<DialogDescription className="mt-4">
|
||||
<Trans>
|
||||
Rest assured, your document is strictly confidential and will never be shared. Only
|
||||
your signing experience will be highlighted. Share your personalized signing card to
|
||||
showcase your signature!
|
||||
Rest assured, your document is strictly confidential and will never be shared. Only your signing
|
||||
experience will be highlighted. Share your personalized signing card to showcase your signature!
|
||||
</Trans>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
@@ -157,8 +150,7 @@ export const DocumentShareButton = ({
|
||||
<div className="flex w-full flex-col">
|
||||
<div className="rounded-md border p-4">
|
||||
I just {token ? 'signed' : 'sent'} a document in style with{' '}
|
||||
<span className="font-medium text-blue-400">@documenso</span>
|
||||
. Check it out!
|
||||
<span className="font-medium text-blue-400">@documenso</span>. Check it out!
|
||||
<span className="mt-2 block" />
|
||||
<span
|
||||
className={cn('break-all font-medium text-blue-400', {
|
||||
@@ -168,12 +160,9 @@ export const DocumentShareButton = ({
|
||||
{NEXT_PUBLIC_WEBAPP_URL()}/share/{shareLink?.slug || '...'}
|
||||
</span>
|
||||
<div
|
||||
className={cn(
|
||||
'mt-4 aspect-[1200/630] overflow-hidden rounded-lg border bg-muted/40',
|
||||
{
|
||||
'animate-pulse': !shareLink?.slug,
|
||||
},
|
||||
)}
|
||||
className={cn('mt-4 aspect-[1200/630] overflow-hidden rounded-lg border bg-muted/40', {
|
||||
'animate-pulse': !shareLink?.slug,
|
||||
})}
|
||||
>
|
||||
{shareLink?.slug && (
|
||||
<img
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { InfoIcon } from 'lucide-react';
|
||||
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip';
|
||||
|
||||
export const DocumentSignatureSettingsTooltip = () => {
|
||||
return (
|
||||
<Tooltip>
|
||||
@@ -10,7 +9,7 @@ export const DocumentSignatureSettingsTooltip = () => {
|
||||
<InfoIcon className="mx-2 h-4 w-4" />
|
||||
</TooltipTrigger>
|
||||
|
||||
<TooltipContent className="text-foreground max-w-md space-y-2 p-4">
|
||||
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
||||
<h2>
|
||||
<strong>
|
||||
<Trans>Signature types</Trans>
|
||||
@@ -18,9 +17,7 @@ export const DocumentSignatureSettingsTooltip = () => {
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<Trans>
|
||||
The types of signatures that recipients are allowed to use when signing the document.
|
||||
</Trans>
|
||||
<Trans>The types of signatures that recipients are allowed to use when signing the document.</Trans>
|
||||
</p>
|
||||
|
||||
<ul className="ml-3.5 list-outside list-disc space-y-0.5 py-2">
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
import { DOCUMENT_VISIBILITY } from '@documenso/lib/constants/document-visibility';
|
||||
import { DocumentVisibility } from '@documenso/lib/types/document-visibility';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@documenso/ui/primitives/select';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { TeamMemberRole } from '@prisma/client';
|
||||
import type { SelectProps } from '@radix-ui/react-select';
|
||||
import { InfoIcon } from 'lucide-react';
|
||||
|
||||
import { DOCUMENT_VISIBILITY } from '@documenso/lib/constants/document-visibility';
|
||||
import { DocumentVisibility } from '@documenso/lib/types/document-visibility';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@documenso/ui/primitives/select';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip';
|
||||
import { forwardRef } from 'react';
|
||||
|
||||
export type DocumentVisibilitySelectType = SelectProps & {
|
||||
currentTeamMemberRole?: string;
|
||||
@@ -26,10 +18,7 @@ export type DocumentVisibilitySelectType = SelectProps & {
|
||||
};
|
||||
|
||||
export const DocumentVisibilitySelect = forwardRef<HTMLButtonElement, DocumentVisibilitySelectType>(
|
||||
(
|
||||
{ currentTeamMemberRole, isTeamSettings = false, disabled, canUpdateVisibility, ...props },
|
||||
ref,
|
||||
) => {
|
||||
({ currentTeamMemberRole, isTeamSettings = false, disabled, canUpdateVisibility, ...props }, ref) => {
|
||||
const { _ } = useLingui();
|
||||
|
||||
const isAdmin = currentTeamMemberRole === TeamMemberRole.ADMIN;
|
||||
@@ -43,13 +32,8 @@ export const DocumentVisibilitySelect = forwardRef<HTMLButtonElement, DocumentVi
|
||||
</SelectTrigger>
|
||||
|
||||
<SelectContent position="popper">
|
||||
<SelectItem value={DocumentVisibility.EVERYONE}>
|
||||
{_(DOCUMENT_VISIBILITY.EVERYONE.value)}
|
||||
</SelectItem>
|
||||
<SelectItem
|
||||
value={DocumentVisibility.MANAGER_AND_ABOVE}
|
||||
disabled={!isAdmin && !isManager}
|
||||
>
|
||||
<SelectItem value={DocumentVisibility.EVERYONE}>{_(DOCUMENT_VISIBILITY.EVERYONE.value)}</SelectItem>
|
||||
<SelectItem value={DocumentVisibility.MANAGER_AND_ABOVE} disabled={!isAdmin && !isManager}>
|
||||
{_(DOCUMENT_VISIBILITY.MANAGER_AND_ABOVE.value)}
|
||||
</SelectItem>
|
||||
<SelectItem value={DocumentVisibility.ADMIN} disabled={!isAdmin}>
|
||||
@@ -89,8 +73,7 @@ export const DocumentVisibilityTooltip = () => {
|
||||
</li>
|
||||
<li>
|
||||
<Trans>
|
||||
<strong>Managers and above</strong> - Only managers and above can access and view the
|
||||
document
|
||||
<strong>Managers and above</strong> - Only managers and above can access and view the document
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import { SigningStatus } from '@prisma/client';
|
||||
import type { Field, Recipient } from '@prisma/client';
|
||||
import { ClockIcon, EyeOffIcon, LockIcon } from 'lucide-react';
|
||||
|
||||
import { getBoundingClientRect } from '@documenso/lib/client-only/get-bounding-client-rect';
|
||||
import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import type { Field, Recipient } from '@prisma/client';
|
||||
import { SigningStatus } from '@prisma/client';
|
||||
import { ClockIcon, EyeOffIcon, LockIcon } from 'lucide-react';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { isTemplateRecipientEmailPlaceholder } from '../../../lib/constants/template';
|
||||
import { extractInitials } from '../../../lib/utils/recipient-formatter';
|
||||
@@ -20,15 +18,7 @@ import { PopoverHover } from '../../primitives/popover';
|
||||
interface EnvelopeRecipientFieldTooltipProps {
|
||||
field: Pick<
|
||||
Field,
|
||||
| 'id'
|
||||
| 'inserted'
|
||||
| 'positionX'
|
||||
| 'positionY'
|
||||
| 'width'
|
||||
| 'height'
|
||||
| 'page'
|
||||
| 'type'
|
||||
| 'fieldMeta'
|
||||
'id' | 'inserted' | 'positionX' | 'positionY' | 'width' | 'height' | 'page' | 'type' | 'fieldMeta'
|
||||
> & {
|
||||
recipient: Pick<Recipient, 'name' | 'email' | 'signingStatus'>;
|
||||
};
|
||||
@@ -70,9 +60,7 @@ export function EnvelopeRecipientFieldTooltip({
|
||||
});
|
||||
|
||||
const calculateCoords = useCallback(() => {
|
||||
const $page = document.querySelector<HTMLElement>(
|
||||
`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${field.page}"]`,
|
||||
);
|
||||
const $page = document.querySelector<HTMLElement>(`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${field.page}"]`);
|
||||
|
||||
if (!$page) {
|
||||
return;
|
||||
@@ -111,9 +99,7 @@ export function EnvelopeRecipientFieldTooltip({
|
||||
}, [calculateCoords]);
|
||||
|
||||
useEffect(() => {
|
||||
const $page = document.querySelector<HTMLElement>(
|
||||
`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${field.page}"]`,
|
||||
);
|
||||
const $page = document.querySelector<HTMLElement>(`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${field.page}"]`);
|
||||
|
||||
if (!$page) {
|
||||
return;
|
||||
@@ -145,8 +131,8 @@ export function EnvelopeRecipientFieldTooltip({
|
||||
>
|
||||
<PopoverHover
|
||||
trigger={
|
||||
<Avatar className="absolute -left-3 -top-3 z-50 h-6 w-6 border-2 border-solid border-gray-200/50 transition-colors hover:border-gray-200">
|
||||
<AvatarFallback className="bg-neutral-50 text-xs text-gray-400">
|
||||
<Avatar className="absolute -top-3 -left-3 z-50 h-6 w-6 border-2 border-gray-200/50 border-solid transition-colors hover:border-gray-200">
|
||||
<AvatarFallback className="bg-neutral-50 text-gray-400 text-xs">
|
||||
{extractInitials(field.recipient.name || field.recipient.email)}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
@@ -191,12 +177,10 @@ export function EnvelopeRecipientFieldTooltip({
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p className="mt-1 text-center text-xs text-muted-foreground">
|
||||
{getRecipientDisplayText(field.recipient)}
|
||||
</p>
|
||||
<p className="mt-1 text-center text-muted-foreground text-xs">{getRecipientDisplayText(field.recipient)}</p>
|
||||
|
||||
<button
|
||||
className="absolute right-0 top-0 my-1 p-2 focus:outline-none focus-visible:ring-0"
|
||||
className="absolute top-0 right-0 my-1 p-2 focus:outline-none focus-visible:ring-0"
|
||||
onClick={() => setHideField(true)}
|
||||
title="Hide field"
|
||||
>
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
import { Plural, Trans } from '@lingui/react/macro';
|
||||
|
||||
import type {
|
||||
TEnvelopeExpirationDurationPeriod,
|
||||
TEnvelopeExpirationPeriod,
|
||||
} from '@documenso/lib/constants/envelope-expiration';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@documenso/ui/primitives/select';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@documenso/ui/primitives/select';
|
||||
import { Plural, Trans } from '@lingui/react/macro';
|
||||
|
||||
type ExpirationMode = 'duration' | 'disabled' | 'inherit';
|
||||
|
||||
@@ -35,9 +28,7 @@ const getAmount = (value: TEnvelopeExpirationPeriod | null | undefined): number
|
||||
return 1;
|
||||
};
|
||||
|
||||
const getUnit = (
|
||||
value: TEnvelopeExpirationPeriod | null | undefined,
|
||||
): TEnvelopeExpirationDurationPeriod['unit'] => {
|
||||
const getUnit = (value: TEnvelopeExpirationPeriod | null | undefined): TEnvelopeExpirationDurationPeriod['unit'] => {
|
||||
if (value && 'unit' in value) {
|
||||
return value.unit;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { Plural, Trans } from '@lingui/react/macro';
|
||||
|
||||
import type {
|
||||
TEnvelopeReminderDurationPeriod,
|
||||
TEnvelopeReminderPeriod,
|
||||
@@ -7,13 +5,8 @@ import type {
|
||||
} from '@documenso/lib/constants/envelope-reminder';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
import { Label } from '@documenso/ui/primitives/label';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@documenso/ui/primitives/select';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@documenso/ui/primitives/select';
|
||||
import { Plural, Trans } from '@lingui/react/macro';
|
||||
|
||||
type ReminderMode = 'enabled' | 'disabled' | 'inherit';
|
||||
|
||||
@@ -37,9 +30,7 @@ const getPeriodAmount = (period: TEnvelopeReminderPeriod | undefined): number =>
|
||||
return 1;
|
||||
};
|
||||
|
||||
const getPeriodUnit = (
|
||||
period: TEnvelopeReminderPeriod | undefined,
|
||||
): TEnvelopeReminderDurationPeriod['unit'] => {
|
||||
const getPeriodUnit = (period: TEnvelopeReminderPeriod | undefined): TEnvelopeReminderDurationPeriod['unit'] => {
|
||||
if (period && 'unit' in period) {
|
||||
return period.unit;
|
||||
}
|
||||
@@ -87,9 +78,7 @@ export const ReminderSettingsPicker = ({
|
||||
});
|
||||
};
|
||||
|
||||
const updateSendAfter = (
|
||||
updates: Partial<{ amount: number; unit: TEnvelopeReminderDurationPeriod['unit'] }>,
|
||||
) => {
|
||||
const updateSendAfter = (updates: Partial<{ amount: number; unit: TEnvelopeReminderDurationPeriod['unit'] }>) => {
|
||||
const newAmount = Math.max(1, Math.floor(updates.amount ?? sendAfterAmount));
|
||||
const newUnit = updates.unit ?? sendAfterUnit;
|
||||
|
||||
@@ -99,9 +88,7 @@ export const ReminderSettingsPicker = ({
|
||||
});
|
||||
};
|
||||
|
||||
const updateRepeatEvery = (
|
||||
updates: Partial<{ amount: number; unit: TEnvelopeReminderDurationPeriod['unit'] }>,
|
||||
) => {
|
||||
const updateRepeatEvery = (updates: Partial<{ amount: number; unit: TEnvelopeReminderDurationPeriod['unit'] }>) => {
|
||||
const newAmount = Math.max(1, Math.floor(updates.amount ?? repeatEveryAmount));
|
||||
const newUnit = updates.unit ?? repeatEveryUnit;
|
||||
|
||||
@@ -151,7 +138,7 @@ export const ReminderSettingsPicker = ({
|
||||
{mode === 'enabled' && (
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label className="text-sm text-muted-foreground">
|
||||
<Label className="text-muted-foreground text-sm">
|
||||
<Trans>Send first reminder after</Trans>
|
||||
</Label>
|
||||
|
||||
@@ -181,7 +168,7 @@ export const ReminderSettingsPicker = ({
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label className="text-sm text-muted-foreground">
|
||||
<Label className="text-muted-foreground text-sm">
|
||||
<Trans>Then repeat every</Trans>
|
||||
</Label>
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { getBoundingClientRect } from '@documenso/lib/client-only/get-bounding-client-rect';
|
||||
import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
|
||||
import type { Field } from '@prisma/client';
|
||||
import { TooltipArrow } from '@radix-ui/react-tooltip';
|
||||
import type { VariantProps } from 'class-variance-authority';
|
||||
import { cva } from 'class-variance-authority';
|
||||
|
||||
import { getBoundingClientRect } from '@documenso/lib/client-only/get-bounding-client-rect';
|
||||
import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { cn } from '../../lib/utils';
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../primitives/tooltip';
|
||||
@@ -26,21 +24,13 @@ const tooltipVariants = cva('font-semibold', {
|
||||
interface EnvelopeFieldToolTipProps extends VariantProps<typeof tooltipVariants> {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
field: Pick<
|
||||
Field,
|
||||
'id' | 'inserted' | 'fieldMeta' | 'positionX' | 'positionY' | 'width' | 'height' | 'page'
|
||||
>;
|
||||
field: Pick<Field, 'id' | 'inserted' | 'fieldMeta' | 'positionX' | 'positionY' | 'width' | 'height' | 'page'>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a tooltip for a given field.
|
||||
*/
|
||||
export function EnvelopeFieldToolTip({
|
||||
children,
|
||||
color,
|
||||
className = '',
|
||||
field,
|
||||
}: EnvelopeFieldToolTipProps) {
|
||||
export function EnvelopeFieldToolTip({ children, color, className = '', field }: EnvelopeFieldToolTipProps) {
|
||||
const [coords, setCoords] = useState({
|
||||
x: 0,
|
||||
y: 0,
|
||||
@@ -49,9 +39,7 @@ export function EnvelopeFieldToolTip({
|
||||
});
|
||||
|
||||
const calculateCoords = useCallback(() => {
|
||||
const $page = document.querySelector<HTMLElement>(
|
||||
`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${field.page}"]`,
|
||||
);
|
||||
const $page = document.querySelector<HTMLElement>(`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${field.page}"]`);
|
||||
|
||||
if (!$page) {
|
||||
return;
|
||||
@@ -90,9 +78,7 @@ export function EnvelopeFieldToolTip({
|
||||
}, [calculateCoords]);
|
||||
|
||||
useEffect(() => {
|
||||
const $page = document.querySelector<HTMLElement>(
|
||||
`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${field.page}"]`,
|
||||
);
|
||||
const $page = document.querySelector<HTMLElement>(`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${field.page}"]`);
|
||||
|
||||
if (!$page) {
|
||||
return;
|
||||
@@ -124,10 +110,7 @@ export function EnvelopeFieldToolTip({
|
||||
<Tooltip delayDuration={0} open={!field.inserted || !field.fieldMeta}>
|
||||
<TooltipTrigger className="absolute inset-0 w-full"></TooltipTrigger>
|
||||
|
||||
<TooltipContent
|
||||
className={tooltipVariants({ color, className: cn(className, 'z-40') })}
|
||||
sideOffset={2}
|
||||
>
|
||||
<TooltipContent className={tooltipVariants({ color, className: cn(className, 'z-40') })} sideOffset={2}>
|
||||
{children}
|
||||
<TooltipArrow />
|
||||
</TooltipContent>
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
import { useFieldPageCoords } from '@documenso/lib/client-only/hooks/use-field-page-coords';
|
||||
import type { Field } from '@prisma/client';
|
||||
import { TooltipArrow } from '@radix-ui/react-tooltip';
|
||||
import type { VariantProps } from 'class-variance-authority';
|
||||
import { cva } from 'class-variance-authority';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
import { useFieldPageCoords } from '@documenso/lib/client-only/hooks/use-field-page-coords';
|
||||
|
||||
import { cn } from '../..//lib/utils';
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from '../..//primitives/tooltip';
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../..//primitives/tooltip';
|
||||
|
||||
const tooltipVariants = cva('font-semibold', {
|
||||
variants: {
|
||||
@@ -29,10 +23,7 @@ const tooltipVariants = cva('font-semibold', {
|
||||
interface FieldToolTipProps extends VariantProps<typeof tooltipVariants> {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
field: Pick<
|
||||
Field,
|
||||
'id' | 'inserted' | 'fieldMeta' | 'positionX' | 'positionY' | 'width' | 'height' | 'page'
|
||||
>;
|
||||
field: Pick<Field, 'id' | 'inserted' | 'fieldMeta' | 'positionX' | 'positionY' | 'width' | 'height' | 'page'>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { type Field, FieldType } from '@prisma/client';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
import { useElementBounds } from '@documenso/lib/client-only/hooks/use-element-bounds';
|
||||
import { useFieldPageCoords } from '@documenso/lib/client-only/hooks/use-field-page-coords';
|
||||
import { useIsPageInDom } from '@documenso/lib/client-only/hooks/use-is-page-in-dom';
|
||||
import {
|
||||
PDF_VIEWER_CONTENT_SELECTOR,
|
||||
PDF_VIEWER_PAGE_SELECTOR,
|
||||
} from '@documenso/lib/constants/pdf-viewer';
|
||||
import { PDF_VIEWER_CONTENT_SELECTOR, PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
|
||||
import { isFieldUnsignedAndRequired } from '@documenso/lib/utils/advanced-fields-helpers';
|
||||
import { type Field, FieldType } from '@prisma/client';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
import type { RecipientColorStyles } from '../../lib/recipient-colors';
|
||||
import { cn } from '../../lib/utils';
|
||||
@@ -21,17 +16,11 @@ export type FieldContainerPortalProps = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
export function FieldContainerPortal({
|
||||
field,
|
||||
children,
|
||||
className = '',
|
||||
}: FieldContainerPortalProps) {
|
||||
export function FieldContainerPortal({ field, children, className = '' }: FieldContainerPortalProps) {
|
||||
const alternativePortalRoot = document.getElementById('document-field-portal-root');
|
||||
|
||||
const coords = useFieldPageCoords(field);
|
||||
const $pageBounds = useElementBounds(
|
||||
`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${field.page}"]`,
|
||||
);
|
||||
const $pageBounds = useElementBounds(`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${field.page}"]`);
|
||||
|
||||
const maxWidth = $pageBounds?.width ? $pageBounds.width - coords.x : undefined;
|
||||
|
||||
@@ -77,13 +66,7 @@ export type FieldRootContainerProps = {
|
||||
readonly?: boolean;
|
||||
};
|
||||
|
||||
export function FieldRootContainer({
|
||||
field,
|
||||
children,
|
||||
color,
|
||||
className,
|
||||
readonly,
|
||||
}: FieldRootContainerProps) {
|
||||
export function FieldRootContainer({ field, children, color, className, readonly }: FieldRootContainerProps) {
|
||||
const [isValidating, setIsValidating] = useState(false);
|
||||
const isPageInDom = useIsPageInDom(field.page);
|
||||
|
||||
@@ -101,10 +84,7 @@ export function FieldRootContainer({
|
||||
// pick up the validation state immediately.
|
||||
const pdfContent = document.querySelector(PDF_VIEWER_CONTENT_SELECTOR);
|
||||
|
||||
if (
|
||||
pdfContent?.getAttribute('data-validate-fields') === 'true' &&
|
||||
isFieldUnsignedAndRequired(field)
|
||||
) {
|
||||
if (pdfContent?.getAttribute('data-validate-fields') === 'true' && isFieldUnsignedAndRequired(field)) {
|
||||
ref.current.setAttribute('data-validate', 'true');
|
||||
setIsValidating(true);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import React from 'react';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { InfoIcon } from 'lucide-react';
|
||||
|
||||
import { DOCUMENT_AUTH_TYPES } from '@documenso/lib/constants/document-auth';
|
||||
import { RecipientActionAuth } from '@documenso/lib/types/document-auth';
|
||||
import { MultiSelect, type Option } from '@documenso/ui/primitives/multiselect';
|
||||
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 { InfoIcon } from 'lucide-react';
|
||||
|
||||
import { cn } from '../../lib/utils';
|
||||
|
||||
@@ -45,15 +42,11 @@ export const RecipientActionAuthSelect = ({
|
||||
|
||||
// Convert string array to Option array for MultiSelect
|
||||
const selectedOptions =
|
||||
(value
|
||||
?.map((val) => authOptions.find((option) => option.value === val))
|
||||
.filter(Boolean) as Option[]) || [];
|
||||
(value?.map((val) => authOptions.find((option) => option.value === val)).filter(Boolean) as Option[]) || [];
|
||||
|
||||
// Convert default value to Option array
|
||||
const defaultOptions =
|
||||
(defaultValue
|
||||
?.map((val) => authOptions.find((option) => option.value === val))
|
||||
.filter(Boolean) as Option[]) || [];
|
||||
(defaultValue?.map((val) => authOptions.find((option) => option.value === val)).filter(Boolean) as Option[]) || [];
|
||||
|
||||
const handleChange = (options: Option[]) => {
|
||||
const values = options.map((option) => option.value);
|
||||
@@ -76,7 +69,7 @@ export const RecipientActionAuthSelect = ({
|
||||
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
className={cn('absolute right-2 top-1/2 -translate-y-1/2', {
|
||||
className={cn('absolute top-1/2 right-2 -translate-y-1/2', {
|
||||
'right-8': selectedOptions.length > 0,
|
||||
})}
|
||||
>
|
||||
@@ -95,28 +88,25 @@ export const RecipientActionAuthSelect = ({
|
||||
</p>
|
||||
|
||||
<p className="mt-2">
|
||||
<Trans>
|
||||
These will override any global settings. Multiple methods can be selected.
|
||||
</Trans>
|
||||
<Trans>These will override any global settings. Multiple methods can be selected.</Trans>
|
||||
</p>
|
||||
|
||||
<ul className="ml-3.5 list-outside list-disc space-y-0.5 py-2">
|
||||
<li>
|
||||
<Trans>
|
||||
<strong>Inherit authentication method</strong> - Use the global action signing
|
||||
authentication method configured in the "General Settings" step
|
||||
<strong>Inherit authentication method</strong> - Use the global action signing authentication method
|
||||
configured in the "General Settings" step
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<Trans>
|
||||
<strong>Require passkey</strong> - The recipient must have an account and passkey
|
||||
configured via their settings
|
||||
<strong>Require passkey</strong> - The recipient must have an account and passkey configured via their
|
||||
settings
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<Trans>
|
||||
<strong>Require 2FA</strong> - The recipient must have an account and 2FA enabled
|
||||
via their settings
|
||||
<strong>Require 2FA</strong> - The recipient must have an account and 2FA enabled via their settings
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { Popover, PopoverContent } from '@documenso/ui/primitives/popover';
|
||||
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { PopoverAnchor } from '@radix-ui/react-popover';
|
||||
|
||||
import { Popover, PopoverContent } from '@documenso/ui/primitives/popover';
|
||||
import type React from 'react';
|
||||
import { useRef, useState } from 'react';
|
||||
|
||||
import { Command, CommandGroup, CommandItem } from '../../primitives/command';
|
||||
import { Input } from '../../primitives/input';
|
||||
@@ -77,11 +77,7 @@ export const RecipientAutoCompleteInput = ({
|
||||
{/* Not using <CommandEmpty /> here due to some weird behaviour */}
|
||||
{options.length === 0 && (
|
||||
<div className="px-2 py-1.5 text-sm">
|
||||
{loading ? (
|
||||
<Trans>Loading suggestions...</Trans>
|
||||
) : (
|
||||
<Trans>No suggestions found</Trans>
|
||||
)}
|
||||
{loading ? <Trans>Loading suggestions...</Trans> : <Trans>No suggestions found</Trans>}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
import { ROLE_ICONS } from '@documenso/ui/primitives/recipient-role-icons';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger } from '@documenso/ui/primitives/select';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { RecipientRole } from '@prisma/client';
|
||||
import type { SelectProps } from '@radix-ui/react-select';
|
||||
import { InfoIcon } from 'lucide-react';
|
||||
|
||||
import { ROLE_ICONS } from '@documenso/ui/primitives/recipient-role-icons';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger } from '@documenso/ui/primitives/select';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip';
|
||||
import { forwardRef } from 'react';
|
||||
|
||||
import { cn } from '../../lib/utils';
|
||||
|
||||
@@ -21,17 +19,7 @@ export type RecipientRoleSelectProps = SelectProps & {
|
||||
};
|
||||
|
||||
export const RecipientRoleSelect = forwardRef<HTMLButtonElement, RecipientRoleSelectProps>(
|
||||
(
|
||||
{
|
||||
hideAssistantRole,
|
||||
hideCCerRole,
|
||||
hideViewerRole,
|
||||
hideApproverRole,
|
||||
isAssistantEnabled = true,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
) => (
|
||||
({ hideAssistantRole, hideCCerRole, hideViewerRole, hideApproverRole, isAssistantEnabled = true, ...props }, ref) => (
|
||||
<Select {...props}>
|
||||
<SelectTrigger ref={ref} className="w-[50px] bg-background p-2" title={props.value}>
|
||||
{/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */}
|
||||
@@ -51,9 +39,7 @@ export const RecipientRoleSelect = forwardRef<HTMLButtonElement, RecipientRoleSe
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="z-9999 max-w-md p-4 text-foreground">
|
||||
<p>
|
||||
<Trans>
|
||||
The recipient is required to sign the document for it to be completed.
|
||||
</Trans>
|
||||
<Trans>The recipient is required to sign the document for it to be completed.</Trans>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
@@ -73,9 +59,7 @@ export const RecipientRoleSelect = forwardRef<HTMLButtonElement, RecipientRoleSe
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="z-9999 max-w-md p-4 text-foreground">
|
||||
<p>
|
||||
<Trans>
|
||||
The recipient is required to approve the document for it to be completed.
|
||||
</Trans>
|
||||
<Trans>The recipient is required to approve the document for it to be completed.</Trans>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
@@ -96,9 +80,7 @@ export const RecipientRoleSelect = forwardRef<HTMLButtonElement, RecipientRoleSe
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="z-9999 max-w-md p-4 text-foreground">
|
||||
<p>
|
||||
<Trans>
|
||||
The recipient is required to view the document for it to be completed.
|
||||
</Trans>
|
||||
<Trans>The recipient is required to view the document for it to be completed.</Trans>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
@@ -120,8 +102,8 @@ export const RecipientRoleSelect = forwardRef<HTMLButtonElement, RecipientRoleSe
|
||||
<TooltipContent className="z-9999 max-w-md p-4 text-foreground">
|
||||
<p>
|
||||
<Trans>
|
||||
The recipient is not required to take any action and receives a copy of the
|
||||
document after it is completed.
|
||||
The recipient is not required to take any action and receives a copy of the document after it is
|
||||
completed.
|
||||
</Trans>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
@@ -134,10 +116,7 @@ export const RecipientRoleSelect = forwardRef<HTMLButtonElement, RecipientRoleSe
|
||||
<SelectItem
|
||||
value={RecipientRole.ASSISTANT}
|
||||
disabled={!isAssistantEnabled}
|
||||
className={cn(
|
||||
!isAssistantEnabled &&
|
||||
'cursor-not-allowed opacity-50 data-[disabled]:pointer-events-auto',
|
||||
)}
|
||||
className={cn(!isAssistantEnabled && 'cursor-not-allowed opacity-50 data-[disabled]:pointer-events-auto')}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<div className="flex w-[150px] items-center">
|
||||
@@ -152,14 +131,10 @@ export const RecipientRoleSelect = forwardRef<HTMLButtonElement, RecipientRoleSe
|
||||
<p>
|
||||
{isAssistantEnabled ? (
|
||||
<Trans>
|
||||
The recipient can prepare the document for later signers by pre-filling
|
||||
suggest values.
|
||||
The recipient can prepare the document for later signers by pre-filling suggest values.
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans>
|
||||
Assistant role is only available when the document is in sequential signing
|
||||
mode.
|
||||
</Trans>
|
||||
<Trans>Assistant role is only available when the document is in sequential signing mode.</Trans>
|
||||
)}
|
||||
</p>
|
||||
</TooltipContent>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import type { Signature } from '@prisma/client';
|
||||
import { animate, motion, useMotionTemplate, useMotionValue, useTransform } from 'framer-motion';
|
||||
import { P, match } from 'ts-pattern';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { match, P } from 'ts-pattern';
|
||||
|
||||
import { cn } from '../lib/utils';
|
||||
import { Card, CardContent } from '../primitives/card';
|
||||
@@ -17,19 +16,12 @@ export type SigningCardProps = {
|
||||
/**
|
||||
* 2D signing card.
|
||||
*/
|
||||
export const SigningCard = ({
|
||||
className,
|
||||
name,
|
||||
signature,
|
||||
signingCelebrationImage,
|
||||
}: SigningCardProps) => {
|
||||
export const SigningCard = ({ className, name, signature, signingCelebrationImage }: SigningCardProps) => {
|
||||
return (
|
||||
<div className={cn('relative w-full max-w-sm md:max-w-md', className)}>
|
||||
<SigningCardContent name={name} signature={signature} />
|
||||
|
||||
{signingCelebrationImage && (
|
||||
<SigningCardImage signingCelebrationImage={signingCelebrationImage} />
|
||||
)}
|
||||
{signingCelebrationImage && <SigningCardImage signingCelebrationImage={signingCelebrationImage} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -37,12 +29,7 @@ export const SigningCard = ({
|
||||
/**
|
||||
* 3D signing card that follows the mouse movement within a certain range.
|
||||
*/
|
||||
export const SigningCard3D = ({
|
||||
className,
|
||||
name,
|
||||
signature,
|
||||
signingCelebrationImage,
|
||||
}: SigningCardProps) => {
|
||||
export const SigningCard3D = ({ className, name, signature, signingCelebrationImage }: SigningCardProps) => {
|
||||
// Should use % based dimensions by calculating the window height/width.
|
||||
const boundary = 400;
|
||||
|
||||
@@ -127,12 +114,9 @@ export const SigningCard3D = ({
|
||||
}, [onMouseMove]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn('relative w-full max-w-sm md:max-w-md', className)}
|
||||
style={{ perspective: 800 }}
|
||||
>
|
||||
<div className={cn('relative w-full max-w-sm md:max-w-md', className)} style={{ perspective: 800 }}>
|
||||
<motion.div
|
||||
className="bg-background w-full rounded-lg [--sheen-color:180_180_180] dark:[--sheen-color:200_200_200]"
|
||||
className="w-full rounded-lg bg-background [--sheen-color:180_180_180] dark:[--sheen-color:200_200_200]"
|
||||
ref={cardRef}
|
||||
style={{
|
||||
perspective: '800',
|
||||
@@ -145,9 +129,7 @@ export const SigningCard3D = ({
|
||||
<SigningCardContent className="bg-transparent" name={name} signature={signature} />
|
||||
</motion.div>
|
||||
|
||||
{signingCelebrationImage && (
|
||||
<SigningCardImage signingCelebrationImage={signingCelebrationImage} />
|
||||
)}
|
||||
{signingCelebrationImage && <SigningCardImage signingCelebrationImage={signingCelebrationImage} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -161,34 +143,25 @@ type SigningCardContentProps = {
|
||||
const SigningCardContent = ({ className, name, signature }: SigningCardContentProps) => {
|
||||
return (
|
||||
<Card
|
||||
className={cn(
|
||||
'group z-10 mx-auto flex aspect-[21/9] w-full items-center justify-center',
|
||||
className,
|
||||
)}
|
||||
className={cn('group z-10 mx-auto flex aspect-[21/9] w-full items-center justify-center', className)}
|
||||
degrees={-145}
|
||||
gradient
|
||||
>
|
||||
<CardContent
|
||||
className="font-signature p-6 text-center"
|
||||
className="p-6 text-center font-signature"
|
||||
style={{
|
||||
container: 'main',
|
||||
}}
|
||||
>
|
||||
{match(signature)
|
||||
.with({ signatureImageAsBase64: P.string }, (signature) => (
|
||||
<img
|
||||
src={signature.signatureImageAsBase64}
|
||||
alt="signature"
|
||||
className="h-full max-w-[100%] dark:invert"
|
||||
/>
|
||||
<img src={signature.signatureImageAsBase64} alt="signature" className="h-full max-w-[100%] dark:invert" />
|
||||
))
|
||||
.with({ typedSignature: P.string }, (signature) => (
|
||||
<span
|
||||
className="text-muted-foreground/60 group-hover:text-primary/80 break-all font-semibold duration-300"
|
||||
className="break-all font-semibold text-muted-foreground/60 duration-300 group-hover:text-primary/80"
|
||||
style={{
|
||||
fontSize: `max(min(4rem, ${(100 / signature.typedSignature.length / 2).toFixed(
|
||||
4,
|
||||
)}cqw), 1.875rem)`,
|
||||
fontSize: `max(min(4rem, ${(100 / signature.typedSignature.length / 2).toFixed(4)}cqw), 1.875rem)`,
|
||||
}}
|
||||
>
|
||||
{signature.typedSignature}
|
||||
@@ -196,7 +169,7 @@ const SigningCardContent = ({ className, name, signature }: SigningCardContentPr
|
||||
))
|
||||
.otherwise(() => (
|
||||
<span
|
||||
className="text-muted-foreground/60 group-hover:text-primary/80 break-all font-semibold duration-300"
|
||||
className="break-all font-semibold text-muted-foreground/60 duration-300 group-hover:text-primary/80"
|
||||
style={{
|
||||
fontSize: `max(min(4rem, ${(100 / name.length / 2).toFixed(4)}cqw), 1.875rem)`,
|
||||
}}
|
||||
|
||||
@@ -1,50 +1,36 @@
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@documenso/ui/primitives/select';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { TemplateType } from '@prisma/client';
|
||||
import type { SelectProps } from '@radix-ui/react-select';
|
||||
import { InfoIcon } from 'lucide-react';
|
||||
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@documenso/ui/primitives/select';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip';
|
||||
import { forwardRef } from 'react';
|
||||
|
||||
export type TemplateTypeSelectProps = SelectProps;
|
||||
|
||||
export const TemplateTypeSelect = forwardRef<HTMLButtonElement, TemplateTypeSelectProps>(
|
||||
({ ...props }, ref) => {
|
||||
useLingui();
|
||||
export const TemplateTypeSelect = forwardRef<HTMLButtonElement, TemplateTypeSelectProps>(({ ...props }, ref) => {
|
||||
useLingui();
|
||||
|
||||
return (
|
||||
<Select {...props}>
|
||||
<SelectTrigger ref={ref} className="bg-background">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
return (
|
||||
<Select {...props}>
|
||||
<SelectTrigger ref={ref} className="bg-background">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
|
||||
<SelectContent>
|
||||
<SelectItem value={TemplateType.PRIVATE}>{t`Private`}</SelectItem>
|
||||
<SelectItem value={TemplateType.PUBLIC}>{t`Public`}</SelectItem>
|
||||
<SelectItem value={TemplateType.ORGANISATION}>{t`Organisation`}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
);
|
||||
},
|
||||
);
|
||||
<SelectContent>
|
||||
<SelectItem value={TemplateType.PRIVATE}>{t`Private`}</SelectItem>
|
||||
<SelectItem value={TemplateType.PUBLIC}>{t`Public`}</SelectItem>
|
||||
<SelectItem value={TemplateType.ORGANISATION}>{t`Organisation`}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
);
|
||||
});
|
||||
|
||||
TemplateTypeSelect.displayName = 'TemplateTypeSelect';
|
||||
|
||||
export const TemplateTypeTooltip = ({
|
||||
organisationTeamCount,
|
||||
}: {
|
||||
organisationTeamCount: number;
|
||||
}) => {
|
||||
export const TemplateTypeTooltip = ({ organisationTeamCount }: { organisationTeamCount: number }) => {
|
||||
return (
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
@@ -65,8 +51,8 @@ export const TemplateTypeTooltip = ({
|
||||
{organisationTeamCount >= 2 && (
|
||||
<p>
|
||||
<Trans>
|
||||
<strong>Organisation</strong> templates are shared across all teams in your
|
||||
organisation but can only be edited by the owning team.
|
||||
<strong>Organisation</strong> templates are shared across all teams in your organisation but can only be
|
||||
edited by the owning team.
|
||||
</Trans>
|
||||
</p>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user