diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 000000000..b03003160 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,55 @@ +tasks: + - init: | + npm i && + npm run dx:up && + cp .env.example .env && + set -a; source .env && + export NEXTAUTH_URL="$(gp url 3000)" && + export NEXT_PUBLIC_WEBAPP_URL="$(gp url 3000)" && + export NEXT_PUBLIC_MARKETING_URL="$(gp url 3001)" + command: npm run d + +ports: + - port: 3000 + visibility: public + onOpen: open-preview + - port: 3001 + visibility: public + onOpen: open-preview + - port: 9000 + visibility: public + onOpen: ignore + - port: 1100 + visibility: private + onOpen: ignore + - port: 2500 + visibility: private + onOpen: ignore + - port: 54320 + visibility: private + onOpen: ignore + + +github: + prebuilds: + master: true + pullRequests: true + pullRequestsFromForks: true + addCheck: true + addComment: true + addBadge: true + +vscode: + extensions: + - aaron-bond.better-comments + - bradlc.vscode-tailwindcss + - dbaeumer.vscode-eslint + - esbenp.prettier-vscode + - mikestead.dotenv + - unifiedjs.vscode-mdx + - GitHub.copilot-chat + - GitHub.copilot-labs + - GitHub.copilot + - GitHub.vscode-pull-request-github + - Prisma.prisma + - VisualStudioExptTeam.vscodeintellicode diff --git a/apps/marketing/src/app/(marketing)/layout.tsx b/apps/marketing/src/app/(marketing)/layout.tsx index 36241e8e2..365d8a5d1 100644 --- a/apps/marketing/src/app/(marketing)/layout.tsx +++ b/apps/marketing/src/app/(marketing)/layout.tsx @@ -2,6 +2,8 @@ import React, { useEffect, useState } from 'react'; +import { usePathname } from 'next/navigation'; + import { cn } from '@documenso/ui/lib/utils'; import { Footer } from '~/components/(marketing)/footer'; @@ -13,6 +15,7 @@ export type MarketingLayoutProps = { export default function MarketingLayout({ children }: MarketingLayoutProps) { const [scrollY, setScrollY] = useState(0); + const pathname = usePathname(); useEffect(() => { const onScroll = () => { @@ -25,7 +28,11 @@ export default function MarketingLayout({ children }: MarketingLayoutProps) { }, []); return ( -
+
5, diff --git a/apps/marketing/src/app/(marketing)/single-player-mode/[token]/success/page.tsx b/apps/marketing/src/app/(marketing)/singleplayer/[token]/success/page.tsx similarity index 100% rename from apps/marketing/src/app/(marketing)/single-player-mode/[token]/success/page.tsx rename to apps/marketing/src/app/(marketing)/singleplayer/[token]/success/page.tsx diff --git a/apps/marketing/src/app/(marketing)/single-player-mode/page.tsx b/apps/marketing/src/app/(marketing)/singleplayer/page.tsx similarity index 99% rename from apps/marketing/src/app/(marketing)/single-player-mode/page.tsx rename to apps/marketing/src/app/(marketing)/singleplayer/page.tsx index 3c76ebac0..0ae72c788 100644 --- a/apps/marketing/src/app/(marketing)/single-player-mode/page.tsx +++ b/apps/marketing/src/app/(marketing)/singleplayer/page.tsx @@ -130,7 +130,7 @@ export default function SinglePlayerModePage() { signer: data.email, }); - router.push(`/single-player-mode/${documentToken}/success`); + router.push(`/singleplayer/${documentToken}/success`); } catch { toast({ title: 'Something went wrong', diff --git a/apps/marketing/src/app/layout.tsx b/apps/marketing/src/app/layout.tsx index f99050512..05206a76f 100644 --- a/apps/marketing/src/app/layout.tsx +++ b/apps/marketing/src/app/layout.tsx @@ -4,6 +4,7 @@ import { Caveat, Inter } from 'next/font/google'; import { FeatureFlagProvider } from '@documenso/lib/client-only/providers/feature-flag'; import { getAllAnonymousFlags } from '@documenso/lib/universal/get-feature-flag'; +import { TrpcProvider } from '@documenso/trpc/react'; import { cn } from '@documenso/ui/lib/utils'; import { Toaster } from '@documenso/ui/primitives/toaster'; @@ -63,7 +64,9 @@ export default async function RootLayout({ children }: { children: React.ReactNo - {children} + + {children} + diff --git a/apps/marketing/src/components/(marketing)/footer.tsx b/apps/marketing/src/components/(marketing)/footer.tsx index b1f5e39bf..11d368c22 100644 --- a/apps/marketing/src/components/(marketing)/footer.tsx +++ b/apps/marketing/src/components/(marketing)/footer.tsx @@ -23,7 +23,7 @@ const SOCIAL_LINKS = [ const FOOTER_LINKS = [ { href: '/pricing', text: 'Pricing' }, - { href: '/single-player-mode', text: 'Single Player Mode' }, + { href: '/singleplayer', text: 'Singleplayer' }, { href: '/blog', text: 'Blog' }, { href: '/open', text: 'Open' }, { href: 'https://shop.documenso.com', text: 'Shop', target: '_blank' }, diff --git a/apps/marketing/src/components/(marketing)/header.tsx b/apps/marketing/src/components/(marketing)/header.tsx index 117f47319..e73e3af83 100644 --- a/apps/marketing/src/components/(marketing)/header.tsx +++ b/apps/marketing/src/components/(marketing)/header.tsx @@ -35,7 +35,7 @@ export const Header = ({ className, ...props }: HeaderProps) => { {isSinglePlayerModeMarketingEnabled && ( Try now! diff --git a/apps/marketing/src/components/(marketing)/hero.tsx b/apps/marketing/src/components/(marketing)/hero.tsx index a6a24131b..4ff8fbcc2 100644 --- a/apps/marketing/src/components/(marketing)/hero.tsx +++ b/apps/marketing/src/components/(marketing)/hero.tsx @@ -134,9 +134,9 @@ export const Hero = ({ className, ...props }: HeroProps) => { variants={HeroTitleVariants} initial="initial" animate="animate" - className="border-primary bg-background hover:bg-muted mx-auto mt-8 w-60 rounded-xl border transition duration-300" + className="border-primary bg-background hover:bg-muted mx-auto mt-8 w-60 rounded-xl border transition-colors duration-300" > - +

Introducing Single Player Mode

diff --git a/apps/marketing/src/components/(marketing)/mobile-navigation.tsx b/apps/marketing/src/components/(marketing)/mobile-navigation.tsx index c9bd07631..a1897ce58 100644 --- a/apps/marketing/src/components/(marketing)/mobile-navigation.tsx +++ b/apps/marketing/src/components/(marketing)/mobile-navigation.tsx @@ -17,8 +17,8 @@ export type MobileNavigationProps = { export const MENU_NAVIGATION_LINKS = [ { - href: '/single-player-mode', - text: 'Single Player Mode', + href: '/singleplayer', + text: 'Singleplayer', }, { href: '/blog', diff --git a/apps/marketing/src/components/(marketing)/password-reveal.tsx b/apps/marketing/src/components/(marketing)/password-reveal.tsx index b31765943..450221339 100644 --- a/apps/marketing/src/components/(marketing)/password-reveal.tsx +++ b/apps/marketing/src/components/(marketing)/password-reveal.tsx @@ -1,9 +1,8 @@ 'use client'; +import { useCopyToClipboard } from '@documenso/lib/client-only/hooks/use-copy-to-clipboard'; import { useToast } from '@documenso/ui/primitives/use-toast'; -import { useCopyToClipboard } from '~/hooks/use-copy-to-clipboard'; - export type PasswordRevealProps = { password: string; }; diff --git a/apps/marketing/src/components/(marketing)/single-player-mode/single-player-mode-success.tsx b/apps/marketing/src/components/(marketing)/single-player-mode/single-player-mode-success.tsx index 0c85fc65c..49a9efcae 100644 --- a/apps/marketing/src/components/(marketing)/single-player-mode/single-player-mode-success.tsx +++ b/apps/marketing/src/components/(marketing)/single-player-mode/single-player-mode-success.tsx @@ -4,14 +4,13 @@ import { useEffect, useState } from 'react'; import Link from 'next/link'; -import { Share } from 'lucide-react'; - import { useFeatureFlags } from '@documenso/lib/client-only/providers/feature-flag'; import { base64 } from '@documenso/lib/universal/base64'; import { getFile } from '@documenso/lib/universal/upload/get-file'; import { DocumentWithRecipient } from '@documenso/prisma/types/document-with-recipient'; import DocumentDialog from '@documenso/ui/components/document/document-dialog'; import { DocumentDownloadButton } from '@documenso/ui/components/document/document-download-button'; +import { DocumentShareButton } from '@documenso/ui/components/document/document-share-button'; import { SigningCard3D } from '@documenso/ui/components/signing-card'; import { cn } from '@documenso/ui/lib/utils'; import { Button } from '@documenso/ui/primitives/button'; @@ -87,11 +86,11 @@ export const SinglePlayerModeSuccess = ({ className, document }: SinglePlayerMod
- {/* TODO: Hook this up */} - + onShowDocumentClick()} loading={isFetchingDocumentFile} - className="col-span-2" + className="z-10 col-span-2" > Show document diff --git a/apps/marketing/src/pages/api/trpc/[trpc].ts b/apps/marketing/src/pages/api/trpc/[trpc].ts new file mode 100644 index 000000000..a42844904 --- /dev/null +++ b/apps/marketing/src/pages/api/trpc/[trpc].ts @@ -0,0 +1,8 @@ +import * as trpcNext from '@documenso/trpc/server/adapters/next'; +import { createTrpcContext } from '@documenso/trpc/server/context'; +import { appRouter } from '@documenso/trpc/server/router'; + +export default trpcNext.createNextApiHandler({ + router: appRouter, + createContext: async ({ req, res }) => createTrpcContext({ req, res }), +}); diff --git a/apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx b/apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx index 4443981f8..234c222eb 100644 --- a/apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx +++ b/apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx @@ -6,13 +6,12 @@ import { Edit, Pencil, Share } from 'lucide-react'; import { useSession } from 'next-auth/react'; import { match } from 'ts-pattern'; +import { useCopyToClipboard } from '@documenso/lib/client-only/hooks/use-copy-to-clipboard'; import { Document, DocumentStatus, Recipient, SigningStatus, User } from '@documenso/prisma/client'; import { trpc } from '@documenso/trpc/react'; import { Button } from '@documenso/ui/primitives/button'; import { useToast } from '@documenso/ui/primitives/use-toast'; -import { useCopyToClipboard } from '~/hooks/use-copy-to-clipboard'; - export type DataTableActionButtonProps = { row: Document & { User: Pick; @@ -47,7 +46,7 @@ export const DataTableActionButton = ({ row }: DataTableActionButtonProps) => { documentId: row.id, }); - await copyToClipboard(`${window.location.origin}/share/${slug}`).catch(() => null); + await copyToClipboard(`${process.env.NEXT_PUBLIC_WEBAPP_URL}/share/${slug}`).catch(() => null); toast({ title: 'Copied to clipboard', diff --git a/apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx b/apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx index 2fb06833b..07ee64259 100644 --- a/apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx +++ b/apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx @@ -18,6 +18,7 @@ import { } from 'lucide-react'; import { useSession } from 'next-auth/react'; +import { useCopyToClipboard } from '@documenso/lib/client-only/hooks/use-copy-to-clipboard'; import { getFile } from '@documenso/lib/universal/upload/get-file'; import { Document, DocumentStatus, Recipient, User } from '@documenso/prisma/client'; import { DocumentWithData } from '@documenso/prisma/types/document-with-data'; @@ -32,8 +33,6 @@ import { } from '@documenso/ui/primitives/dropdown-menu'; import { useToast } from '@documenso/ui/primitives/use-toast'; -import { useCopyToClipboard } from '~/hooks/use-copy-to-clipboard'; - import { DeleteDraftDocumentDialog } from './delete-draft-document-dialog'; export type DataTableActionDropdownProps = { @@ -61,7 +60,7 @@ export const DataTableActionDropdown = ({ row }: DataTableActionDropdownProps) = const isOwner = row.User.id === session.user.id; // const isRecipient = !!recipient; - // const isDraft = row.status === DocumentStatus.DRAFT; + const isDraft = row.status === DocumentStatus.DRAFT; // const isPending = row.status === DocumentStatus.PENDING; const isComplete = row.status === DocumentStatus.COMPLETED; // const isSigned = recipient?.signingStatus === SigningStatus.SIGNED; @@ -73,7 +72,7 @@ export const DataTableActionDropdown = ({ row }: DataTableActionDropdownProps) = documentId: row.id, }); - await copyToClipboard(`${window.location.origin}/share/${slug}`).catch(() => null); + await copyToClipboard(`${process.env.NEXT_PUBLIC_WEBAPP_URL}/share/${slug}`).catch(() => null); toast({ title: 'Copied to clipboard', @@ -166,7 +165,7 @@ export const DataTableActionDropdown = ({ row }: DataTableActionDropdownProps) = Resend - + {isCreatingShareLink ? ( ) : ( diff --git a/apps/web/src/app/(signing)/sign/[token]/complete/page.tsx b/apps/web/src/app/(signing)/sign/[token]/complete/page.tsx index 414a6624b..5402d12cb 100644 --- a/apps/web/src/app/(signing)/sign/[token]/complete/page.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/complete/page.tsx @@ -9,12 +9,11 @@ import { getFieldsForToken } from '@documenso/lib/server-only/field/get-fields-f import { getRecipientByToken } from '@documenso/lib/server-only/recipient/get-recipient-by-token'; import { DocumentStatus, FieldType } from '@documenso/prisma/client'; import { DocumentDownloadButton } from '@documenso/ui/components/document/document-download-button'; +import { DocumentShareButton } from '@documenso/ui/components/document/document-share-button'; import { SigningCard3D } from '@documenso/ui/components/signing-card'; import signingCelebration from '~/assets/signing-celebration.png'; -import { ShareButton } from './share-button'; - export type CompletedSigningPageProps = { params: { token?: string; @@ -89,7 +88,7 @@ export default async function CompletedSigningPage({ ))}
- + { const [showSignatureModal, setShowSignatureModal] = useState(false); const [localSignature, setLocalSignature] = useState(null); + const [isLocalSignatureSet, setIsLocalSignatureSet] = useState(false); const state = useMemo(() => { if (!field.inserted) { @@ -61,9 +62,16 @@ export const SignatureField = ({ field, recipient }: SignatureFieldProps) => { return 'signed-text'; }, [field.inserted, signature?.signatureImageAsBase64]); + useEffect(() => { + if (!showSignatureModal && !isLocalSignatureSet) { + setLocalSignature(null); + } + }, [showSignatureModal, isLocalSignatureSet]); + const onSign = async (source: 'local' | 'provider' = 'provider') => { try { if (!providedSignature && !localSignature) { + setIsLocalSignatureSet(false); setShowSignatureModal(true); return; } @@ -178,6 +186,7 @@ export const SignatureField = ({ field, recipient }: SignatureFieldProps) => { disabled={!localSignature} onClick={() => { setShowSignatureModal(false); + setIsLocalSignatureSet(true); void onSign('local'); }} > diff --git a/apps/web/src/components/forms/profile.tsx b/apps/web/src/components/forms/profile.tsx index 0082147b4..0630bfdd1 100644 --- a/apps/web/src/components/forms/profile.tsx +++ b/apps/web/src/components/forms/profile.tsx @@ -117,7 +117,8 @@ export const ProfileForm = ({ className, user }: ProfileFormProps) => { name="signature" render={({ field: { onChange } }) => ( onChange(v ?? '')} /> diff --git a/apps/web/src/components/forms/signup.tsx b/apps/web/src/components/forms/signup.tsx index 7d8100c26..a1f3ab81e 100644 --- a/apps/web/src/components/forms/signup.tsx +++ b/apps/web/src/components/forms/signup.tsx @@ -147,7 +147,8 @@ export const SignUpForm = ({ className }: SignUpFormProps) => { name="signature" render={({ field: { onChange } }) => ( onChange(v ?? '')} /> )} diff --git a/apps/web/src/hooks/use-copy-to-clipboard.ts b/apps/web/src/hooks/use-copy-to-clipboard.ts deleted file mode 100644 index d449ded16..000000000 --- a/apps/web/src/hooks/use-copy-to-clipboard.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { useState } from 'react'; - -export type CopiedValue = string | null; -export type CopyFn = (_text: string) => Promise; - -export function useCopyToClipboard(): [CopiedValue, CopyFn] { - const [copiedText, setCopiedText] = useState(null); - - const copy: CopyFn = async (text) => { - if (!navigator?.clipboard) { - console.warn('Clipboard not supported'); - return false; - } - - // Try to save to clipboard then save it in the state if worked - try { - await navigator.clipboard.writeText(text); - setCopiedText(text); - return true; - } catch (error) { - console.warn('Copy failed', error); - setCopiedText(null); - return false; - } - }; - - return [copiedText, copy]; -} diff --git a/apps/marketing/src/hooks/use-copy-to-clipboard.ts b/packages/lib/client-only/hooks/use-copy-to-clipboard.ts similarity index 100% rename from apps/marketing/src/hooks/use-copy-to-clipboard.ts rename to packages/lib/client-only/hooks/use-copy-to-clipboard.ts diff --git a/packages/lib/client-only/hooks/use-element-scale-size.ts b/packages/lib/client-only/hooks/use-element-scale-size.ts index 3e9b34b3f..1c8ab320e 100644 --- a/packages/lib/client-only/hooks/use-element-scale-size.ts +++ b/packages/lib/client-only/hooks/use-element-scale-size.ts @@ -60,26 +60,17 @@ export const calculateTextScaleSize = ( */ export function useElementScaleSize( container: { width: number; height: number }, - child: RefObject, + text: string, fontSize: number, fontFamily: string, ) { const [scalingFactor, setScalingFactor] = useState(1); useEffect(() => { - if (!child.current) { - return; - } - - const scaleSize = calculateTextScaleSize( - container, - child.current.innerText, - `${fontSize}px`, - fontFamily, - ); + const scaleSize = calculateTextScaleSize(container, text, `${fontSize}px`, fontFamily); setScalingFactor(scaleSize); - }, [child, container, fontFamily, fontSize]); + }, [text, container, fontFamily, fontSize]); return scalingFactor; } diff --git a/packages/prisma/migrations/20231013012902_add_document_share_link_delete_cascade/migration.sql b/packages/prisma/migrations/20231013012902_add_document_share_link_delete_cascade/migration.sql new file mode 100644 index 000000000..ca4142a1f --- /dev/null +++ b/packages/prisma/migrations/20231013012902_add_document_share_link_delete_cascade/migration.sql @@ -0,0 +1,5 @@ +-- DropForeignKey +ALTER TABLE "DocumentShareLink" DROP CONSTRAINT "DocumentShareLink_documentId_fkey"; + +-- AddForeignKey +ALTER TABLE "DocumentShareLink" ADD CONSTRAINT "DocumentShareLink_documentId_fkey" FOREIGN KEY ("documentId") REFERENCES "Document"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 266f8470a..4ea322694 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -219,7 +219,7 @@ model DocumentShareLink { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt - document Document @relation(fields: [documentId], references: [id]) + document Document @relation(fields: [documentId], references: [id], onDelete: Cascade) @@unique([documentId, email]) } diff --git a/apps/web/src/app/(signing)/sign/[token]/complete/share-button.tsx b/packages/ui/components/document/document-share-button.tsx similarity index 81% rename from apps/web/src/app/(signing)/sign/[token]/complete/share-button.tsx rename to packages/ui/components/document/document-share-button.tsx index c76d3d7c5..4e7ee1a94 100644 --- a/apps/web/src/app/(signing)/sign/[token]/complete/share-button.tsx +++ b/packages/ui/components/document/document-share-button.tsx @@ -5,8 +5,10 @@ import { HTMLAttributes, useState } from 'react'; import { Copy, Share } from 'lucide-react'; import { FaXTwitter } from 'react-icons/fa6'; +import { useCopyToClipboard } from '@documenso/lib/client-only/hooks/use-copy-to-clipboard'; import { generateTwitterIntent } from '@documenso/lib/universal/generate-twitter-intent'; import { trpc } from '@documenso/trpc/react'; +import { cn } from '@documenso/ui/lib/utils'; import { Button } from '@documenso/ui/primitives/button'; import { Dialog, @@ -18,14 +20,12 @@ import { } from '@documenso/ui/primitives/dialog'; import { useToast } from '@documenso/ui/primitives/use-toast'; -import { useCopyToClipboard } from '~/hooks/use-copy-to-clipboard'; - -export type ShareButtonProps = HTMLAttributes & { +export type DocumentShareButtonProps = HTMLAttributes & { token: string; documentId: number; }; -export const ShareButton = ({ token, documentId }: ShareButtonProps) => { +export const DocumentShareButton = ({ token, documentId, className }: DocumentShareButtonProps) => { const { toast } = useToast(); const [, copyToClipboard] = useCopyToClipboard(); @@ -60,7 +60,7 @@ export const ShareButton = ({ token, documentId }: ShareButtonProps) => { slug = result.slug; } - await copyToClipboard(`${window.location.origin}/share/${slug}`).catch(() => null); + await copyToClipboard(`${process.env.NEXT_PUBLIC_WEBAPP_URL}/share/${slug}`).catch(() => null); toast({ title: 'Copied to clipboard', @@ -85,7 +85,7 @@ export const ShareButton = ({ token, documentId }: ShareButtonProps) => { window.open( generateTwitterIntent( `I just ${token ? 'signed' : 'sent'} a document with @documenso. Check it out!`, - `${window.location.origin}/share/${slug}`, + `${process.env.NEXT_PUBLIC_WEBAPP_URL}/share/${slug}`, ), '_blank', ); @@ -99,7 +99,7 @@ export const ShareButton = ({ token, documentId }: ShareButtonProps) => {
diff --git a/packages/ui/components/signing-card.tsx b/packages/ui/components/signing-card.tsx index 24a6b6e28..3c65ba9dc 100644 --- a/packages/ui/components/signing-card.tsx +++ b/packages/ui/components/signing-card.tsx @@ -56,7 +56,7 @@ export const SigningCard3D = ({ className, name, signingCelebrationImage }: Sign const sheenGradient = useMotionTemplate`linear-gradient( 30deg, transparent, - rgba(var(--sheen-color) / ${trackMouse ? sheenOpacity : 0}) ${sheenPosition}%, + rgba(var(--sheen-color) / ${sheenOpacity}) ${sheenPosition}%, transparent)`; const cardRef = useRef(null); @@ -98,10 +98,12 @@ export const SigningCard3D = ({ className, name, signingCelebrationImage }: Sign void animate(cardX, 0, { duration: 2, ease: 'backInOut' }); void animate(cardY, 0, { duration: 2, ease: 'backInOut' }); + void animate(sheenOpacity, 0, { duration: 2, ease: 'backInOut' }); + setTrackMouse(false); }, 1000); }, - [cardX, cardY, cardCenterPosition, trackMouse], + [cardX, cardY, cardCenterPosition, trackMouse, sheenOpacity], ); useEffect(() => { @@ -126,7 +128,6 @@ export const SigningCard3D = ({ className, name, signingCelebrationImage }: Sign transformStyle: 'preserve-3d', rotateX, rotateY, - // willChange: 'transform background-image', }} > diff --git a/packages/ui/primitives/document-flow/single-player-mode-fields.tsx b/packages/ui/primitives/document-flow/single-player-mode-fields.tsx index 022b05d60..04c093efc 100644 --- a/packages/ui/primitives/document-flow/single-player-mode-fields.tsx +++ b/packages/ui/primitives/document-flow/single-player-mode-fields.tsx @@ -70,25 +70,23 @@ export function SinglePlayerModeSignatureField({ throw new Error('Invalid field type'); } - const $paragraphEl = useRef(null); - const { height, width } = useFieldPageCoords(field); + const insertedBase64Signature = field.inserted && field.Signature?.signatureImageAsBase64; + const insertedTypeSignature = field.inserted && field.Signature?.typedSignature; + const scalingFactor = useElementScaleSize( { height, width, }, - $paragraphEl, + insertedTypeSignature || '', maxFontSize, fontVariableValue, ); const fontSize = maxFontSize * scalingFactor; - const insertedBase64Signature = field.inserted && field.Signature?.signatureImageAsBase64; - const insertedTypeSignature = field.inserted && field.Signature?.typedSignature; - return ( {insertedBase64Signature ? ( @@ -99,7 +97,6 @@ export function SinglePlayerModeSignatureField({ /> ) : insertedTypeSignature ? (

, 'onChange'> & { onChange?: (_signatureDataUrl: string | null) => void; + containerClassName?: string; }; export const SignaturePad = ({ className, + containerClassName, defaultValue, onChange, ...props @@ -210,7 +212,7 @@ export const SignaturePad = ({ }, [defaultValue]); return ( -

+