mirror of
https://github.com/documenso/documenso.git
synced 2026-08-15 11:01:47 +10:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82e0b4a845 | ||
|
|
4db4821288 | ||
|
|
d9164a3ba3 | ||
|
|
aedcc630ba | ||
|
|
4eceb03ac3 | ||
|
|
11970a3659 |
@@ -10,7 +10,6 @@
|
|||||||
"postinstall": "fumadocs-mdx"
|
"postinstall": "fumadocs-mdx"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-tabs": "^1.1.13",
|
|
||||||
"fumadocs-core": "16.5.0",
|
"fumadocs-core": "16.5.0",
|
||||||
"fumadocs-mdx": "14.2.6",
|
"fumadocs-mdx": "14.2.6",
|
||||||
"fumadocs-ui": "16.5.0",
|
"fumadocs-ui": "16.5.0",
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "18.3.27",
|
"@types/react": "^19.2.17",
|
||||||
"typescript": "5.6.2"
|
"typescript": "5.6.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { msg } from '@lingui/core/macro';
|
|||||||
import { useLingui } from '@lingui/react';
|
import { useLingui } from '@lingui/react';
|
||||||
import { Trans } from '@lingui/react/macro';
|
import { Trans } from '@lingui/react/macro';
|
||||||
import { keepPreviousData } from '@tanstack/react-query';
|
import { keepPreviousData } from '@tanstack/react-query';
|
||||||
import { commandScore } from 'cmdk/dist/command-score';
|
import { defaultFilter as commandScore } from 'cmdk';
|
||||||
import {
|
import {
|
||||||
ArrowLeftIcon,
|
ArrowLeftIcon,
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
|
|||||||
@@ -146,14 +146,17 @@ export const DocumentSigningRadioField = ({ field, onSignField, onUnsignField }:
|
|||||||
{isLoading && <DocumentSigningFieldsLoader />}
|
{isLoading && <DocumentSigningFieldsLoader />}
|
||||||
|
|
||||||
{!field.inserted && (
|
{!field.inserted && (
|
||||||
<RadioGroup onValueChange={(value) => handleSelectItem(value)} className="z-10 my-0.5 gap-y-1">
|
<RadioGroup
|
||||||
|
value={selectedOption}
|
||||||
|
onValueChange={(value) => handleSelectItem(value)}
|
||||||
|
className="z-10 my-0.5 gap-y-1"
|
||||||
|
>
|
||||||
{values?.map((item, index) => (
|
{values?.map((item, index) => (
|
||||||
<div key={index} className="flex items-center">
|
<div key={index} className="flex items-center">
|
||||||
<RadioGroupItem
|
<RadioGroupItem
|
||||||
className="h-3 w-3 shrink-0"
|
className="h-3 w-3 shrink-0"
|
||||||
value={item.value}
|
value={item.value}
|
||||||
id={`option-${field.id}-${item.id}`}
|
id={`option-${field.id}-${item.id}`}
|
||||||
checked={item.checked}
|
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
/>
|
/>
|
||||||
{!item.value.includes('empty-value-') && item.value && (
|
{!item.value.includes('empty-value-') && item.value && (
|
||||||
@@ -167,14 +170,13 @@ export const DocumentSigningRadioField = ({ field, onSignField, onUnsignField }:
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{field.inserted && (
|
{field.inserted && (
|
||||||
<RadioGroup className="my-0.5 gap-y-1">
|
<RadioGroup value={field.customText ?? ''} className="my-0.5 gap-y-1">
|
||||||
{values?.map((item, index) => (
|
{values?.map((item, index) => (
|
||||||
<div key={index} className="flex items-center">
|
<div key={index} className="flex items-center">
|
||||||
<RadioGroupItem
|
<RadioGroupItem
|
||||||
className="h-3 w-3"
|
className="h-3 w-3"
|
||||||
value={item.value}
|
value={item.value}
|
||||||
id={`option-${field.id}-${item.id}`}
|
id={`option-${field.id}-${item.id}`}
|
||||||
checked={item.value === field.customText}
|
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
/>
|
/>
|
||||||
{!item.value.includes('empty-value-') && item.value && (
|
{!item.value.includes('empty-value-') && item.value && (
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ export default function PDFViewer({
|
|||||||
|
|
||||||
type VirtualizedPageListProps = {
|
type VirtualizedPageListProps = {
|
||||||
scrollParentRef: ScrollTarget;
|
scrollParentRef: ScrollTarget;
|
||||||
constraintRef: React.RefObject<HTMLDivElement>;
|
constraintRef: React.RefObject<HTMLDivElement | null>;
|
||||||
pages: PageMeta[];
|
pages: PageMeta[];
|
||||||
numPages: number;
|
numPages: number;
|
||||||
pdf: pdfjsLib.PDFDocumentProxy;
|
pdf: pdfjsLib.PDFDocumentProxy;
|
||||||
|
|||||||
@@ -31,6 +31,26 @@ function initPosthog() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Surfaces hydration recoveries (React 19 discards the server HTML and
|
||||||
|
* re-renders on the client instead of dying) so we can track how often
|
||||||
|
* extensions/early clicks interfere with hydration in the wild.
|
||||||
|
*/
|
||||||
|
function onRecoverableError(error: unknown, errorInfo: { componentStack?: string }) {
|
||||||
|
console.error('[hydration] recovered from error', error, errorInfo.componentStack);
|
||||||
|
|
||||||
|
if (extractPostHogConfig()) {
|
||||||
|
void import('posthog-js').then(({ default: posthog }) => {
|
||||||
|
if (posthog.__loaded) {
|
||||||
|
posthog.capture('$hydration_recoverable_error', {
|
||||||
|
message: error instanceof Error ? error.message : String(error),
|
||||||
|
componentStack: errorInfo.componentStack,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const locale = detect(fromHtmlTag('lang')) || 'en';
|
const locale = detect(fromHtmlTag('lang')) || 'en';
|
||||||
|
|
||||||
@@ -44,6 +64,7 @@ async function main() {
|
|||||||
<HydratedRouter />
|
<HydratedRouter />
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
</StrictMode>,
|
</StrictMode>,
|
||||||
|
{ onRecoverableError },
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -57,9 +57,9 @@
|
|||||||
"papaparse": "^5.5.3",
|
"papaparse": "^5.5.3",
|
||||||
"posthog-js": "^1.297.2",
|
"posthog-js": "^1.297.2",
|
||||||
"posthog-node": "4.18.0",
|
"posthog-node": "4.18.0",
|
||||||
"react": "^18",
|
"react": "^19.2.7",
|
||||||
"react-call": "^1.8.1",
|
"react-call": "^1.8.1",
|
||||||
"react-dom": "^18",
|
"react-dom": "^19.2.7",
|
||||||
"react-dropzone": "^14.3.8",
|
"react-dropzone": "^14.3.8",
|
||||||
"react-hook-form": "^7.66.1",
|
"react-hook-form": "^7.66.1",
|
||||||
"react-hotkeys-hook": "^4.6.2",
|
"react-hotkeys-hook": "^4.6.2",
|
||||||
@@ -93,8 +93,8 @@
|
|||||||
"@types/luxon": "^3.7.1",
|
"@types/luxon": "^3.7.1",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/papaparse": "^5.5.0",
|
"@types/papaparse": "^5.5.0",
|
||||||
"@types/react": "18.3.27",
|
"@types/react": "^19.2.17",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@types/ua-parser-js": "^0.7.39",
|
"@types/ua-parser-js": "^0.7.39",
|
||||||
"cross-env": "^10.1.0",
|
"cross-env": "^10.1.0",
|
||||||
"esbuild": "^0.27.0",
|
"esbuild": "^0.27.0",
|
||||||
|
|||||||
Generated
+1366
-2266
File diff suppressed because it is too large
Load Diff
+38
-4
@@ -48,14 +48,16 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "2.4.8",
|
"@biomejs/biome": "2.4.8",
|
||||||
|
"@types/react": "^19.2.17",
|
||||||
|
"@types/react-dom": "^19.2.3",
|
||||||
"@commitlint/cli": "^20.1.0",
|
"@commitlint/cli": "^20.1.0",
|
||||||
"@commitlint/config-conventional": "^20.0.0",
|
"@commitlint/config-conventional": "^20.0.0",
|
||||||
"@datadog/pprof": "^5.13.5",
|
"@datadog/pprof": "^5.13.5",
|
||||||
"@lingui/cli": "^5.6.0",
|
"@lingui/cli": "^5.6.0",
|
||||||
"@prisma/client": "^6.19.0",
|
"@prisma/client": "^6.19.0",
|
||||||
"@trpc/client": "11.8.1",
|
"@trpc/client": "11.17.0",
|
||||||
"@trpc/react-query": "11.8.1",
|
"@trpc/react-query": "11.17.0",
|
||||||
"@trpc/server": "11.8.1",
|
"@trpc/server": "11.17.0",
|
||||||
"@ts-rest/core": "^3.52.1",
|
"@ts-rest/core": "^3.52.1",
|
||||||
"@ts-rest/open-api": "^3.52.1",
|
"@ts-rest/open-api": "^3.52.1",
|
||||||
"@ts-rest/serverless": "^3.52.1",
|
"@ts-rest/serverless": "^3.52.1",
|
||||||
@@ -92,12 +94,40 @@
|
|||||||
"@lingui/conf": "^5.6.0",
|
"@lingui/conf": "^5.6.0",
|
||||||
"@lingui/core": "^5.6.0",
|
"@lingui/core": "^5.6.0",
|
||||||
"@prisma/extension-read-replicas": "^0.4.1",
|
"@prisma/extension-read-replicas": "^0.4.1",
|
||||||
|
"@radix-ui/react-accordion": "^1.2.16",
|
||||||
|
"@radix-ui/react-alert-dialog": "^1.1.19",
|
||||||
|
"@radix-ui/react-aspect-ratio": "^1.1.11",
|
||||||
|
"@radix-ui/react-avatar": "^1.2.2",
|
||||||
|
"@radix-ui/react-checkbox": "^1.3.7",
|
||||||
|
"@radix-ui/react-collapsible": "^1.1.16",
|
||||||
|
"@radix-ui/react-context-menu": "^2.3.3",
|
||||||
|
"@radix-ui/react-dialog": "^1.1.19",
|
||||||
|
"@radix-ui/react-dropdown-menu": "^2.1.20",
|
||||||
|
"@radix-ui/react-hover-card": "^1.1.19",
|
||||||
|
"@radix-ui/react-label": "^2.1.11",
|
||||||
|
"@radix-ui/react-menubar": "^1.1.20",
|
||||||
|
"@radix-ui/react-navigation-menu": "^1.2.18",
|
||||||
|
"@radix-ui/react-popover": "^1.1.19",
|
||||||
|
"@radix-ui/react-progress": "^1.1.12",
|
||||||
|
"@radix-ui/react-radio-group": "^1.4.3",
|
||||||
|
"@radix-ui/react-scroll-area": "^1.2.14",
|
||||||
|
"@radix-ui/react-select": "^2.3.3",
|
||||||
|
"@radix-ui/react-separator": "^1.1.11",
|
||||||
|
"@radix-ui/react-slider": "^1.4.3",
|
||||||
|
"@radix-ui/react-slot": "^1.3.0",
|
||||||
|
"@radix-ui/react-switch": "^1.3.3",
|
||||||
|
"@radix-ui/react-tabs": "^1.1.17",
|
||||||
|
"@radix-ui/react-toast": "^1.2.19",
|
||||||
|
"@radix-ui/react-toggle": "^1.1.14",
|
||||||
|
"@radix-ui/react-toggle-group": "^1.1.15",
|
||||||
|
"@radix-ui/react-tooltip": "^1.2.12",
|
||||||
"ai": "^5.0.104",
|
"ai": "^5.0.104",
|
||||||
"cron-parser": "^5.5.0",
|
"cron-parser": "^5.5.0",
|
||||||
"luxon": "^3.7.2",
|
"luxon": "^3.7.2",
|
||||||
"patch-package": "^8.0.1",
|
"patch-package": "^8.0.1",
|
||||||
"posthog-node": "4.18.0",
|
"posthog-node": "4.18.0",
|
||||||
"react": "^18",
|
"react": "^19.2.7",
|
||||||
|
"react-dom": "^19.2.7",
|
||||||
"typescript": "5.6.2",
|
"typescript": "5.6.2",
|
||||||
"@marsidev/react-turnstile": "^1.5.0",
|
"@marsidev/react-turnstile": "^1.5.0",
|
||||||
"zod": "^3.25.76"
|
"zod": "^3.25.76"
|
||||||
@@ -106,6 +136,10 @@
|
|||||||
"lodash": "4.18.1",
|
"lodash": "4.18.1",
|
||||||
"pdfjs-dist": "5.4.296",
|
"pdfjs-dist": "5.4.296",
|
||||||
"postcss": "^8.5.19",
|
"postcss": "^8.5.19",
|
||||||
|
"react": "$react",
|
||||||
|
"react-dom": "$react-dom",
|
||||||
|
"@types/react": "^19.2.17",
|
||||||
|
"@types/react-dom": "^19.2.3",
|
||||||
"typescript": "5.6.2",
|
"typescript": "5.6.2",
|
||||||
"zod": "$zod",
|
"zod": "$zod",
|
||||||
"fumadocs-mdx": {
|
"fumadocs-mdx": {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
"arctic": "^3.7.0",
|
"arctic": "^3.7.0",
|
||||||
"hono": "^4.12.14",
|
"hono": "^4.12.14",
|
||||||
"luxon": "^3.7.2",
|
"luxon": "^3.7.2",
|
||||||
"react": "^18",
|
"react": "^19.2.7",
|
||||||
"ts-pattern": "^5.9.0",
|
"ts-pattern": "^5.9.0",
|
||||||
"zod": "^3.25.76"
|
"zod": "^3.25.76"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
export { Body } from '@react-email/body';
|
export {
|
||||||
export { Button } from '@react-email/button';
|
Body,
|
||||||
export { Column } from '@react-email/column';
|
Button,
|
||||||
export { Container } from '@react-email/container';
|
Column,
|
||||||
export { Font } from '@react-email/font';
|
Container,
|
||||||
export { Head } from '@react-email/head';
|
Font,
|
||||||
export { Heading } from '@react-email/heading';
|
Head,
|
||||||
export { Hr } from '@react-email/hr';
|
Heading,
|
||||||
export { Html } from '@react-email/html';
|
Hr,
|
||||||
export { Img } from '@react-email/img';
|
Html,
|
||||||
export { Link } from '@react-email/link';
|
Img,
|
||||||
export { Preview } from '@react-email/preview';
|
Link,
|
||||||
export { render } from '@react-email/render';
|
Preview,
|
||||||
export { Row } from '@react-email/row';
|
Row,
|
||||||
export { Section } from '@react-email/section';
|
render,
|
||||||
export { Tailwind } from '@react-email/tailwind';
|
Section,
|
||||||
export { Text } from '@react-email/text';
|
Tailwind,
|
||||||
|
Text,
|
||||||
|
} from 'react-email';
|
||||||
|
|||||||
@@ -19,27 +19,9 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@documenso/nodemailer-resend": "5.0.0",
|
"@documenso/nodemailer-resend": "5.0.0",
|
||||||
"@documenso/tailwind-config": "*",
|
"@documenso/tailwind-config": "*",
|
||||||
"@react-email/body": "0.2.0",
|
"@react-email/render": "2.1.0",
|
||||||
"@react-email/button": "0.2.0",
|
|
||||||
"@react-email/code-block": "0.2.0",
|
|
||||||
"@react-email/code-inline": "0.0.5",
|
|
||||||
"@react-email/column": "0.0.13",
|
|
||||||
"@react-email/container": "0.0.15",
|
|
||||||
"@react-email/font": "0.0.9",
|
|
||||||
"@react-email/head": "0.0.12",
|
|
||||||
"@react-email/heading": "0.0.15",
|
|
||||||
"@react-email/hr": "0.0.11",
|
|
||||||
"@react-email/html": "0.0.11",
|
|
||||||
"@react-email/img": "0.0.11",
|
|
||||||
"@react-email/link": "0.0.12",
|
|
||||||
"@react-email/preview": "0.0.13",
|
|
||||||
"@react-email/render": "2.0.0",
|
|
||||||
"@react-email/row": "0.0.12",
|
|
||||||
"@react-email/section": "0.0.16",
|
|
||||||
"@react-email/tailwind": "^2.0.1",
|
|
||||||
"@react-email/text": "0.1.5",
|
|
||||||
"nodemailer": "^9.0.0",
|
"nodemailer": "^9.0.0",
|
||||||
"react-email": "^5.0.6",
|
"react-email": "^6.9.0",
|
||||||
"resend": "^6.5.2"
|
"resend": "^6.5.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ type SaveRequest<T, R> = {
|
|||||||
export const useAutoSave = <T, R = void>(onSave: (data: T) => Promise<R>, options: { delay?: number } = {}) => {
|
export const useAutoSave = <T, R = void>(onSave: (data: T) => Promise<R>, options: { delay?: number } = {}) => {
|
||||||
const { delay = 2000 } = options;
|
const { delay = 2000 } = options;
|
||||||
|
|
||||||
const saveTimeoutRef = useRef<NodeJS.Timeout>();
|
const saveTimeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||||
const saveQueueRef = useRef<SaveRequest<T, R>[]>([]);
|
const saveQueueRef = useRef<SaveRequest<T, R>[]>([]);
|
||||||
const isProcessingRef = useRef(false);
|
const isProcessingRef = useRef(false);
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { useToast } from '@documenso/ui/primitives/use-toast';
|
|||||||
import { useLingui } from '@lingui/react/macro';
|
import { useLingui } from '@lingui/react/macro';
|
||||||
import { EnvelopeType, Prisma, ReadStatus, SendStatus, SigningStatus } from '@prisma/client';
|
import { EnvelopeType, Prisma, ReadStatus, SendStatus, SigningStatus } from '@prisma/client';
|
||||||
import type React from 'react';
|
import type React from 'react';
|
||||||
import { createContext, useCallback, useContext, useMemo, useRef, useState } from 'react';
|
import { createContext, useCallback, useContext, useMemo, useRef, useState, useSyncExternalStore } from 'react';
|
||||||
import { useSearchParams } from 'react-router';
|
import { useSearchParams } from 'react-router';
|
||||||
|
|
||||||
import type { TDocumentEmailSettings } from '../../types/document-email';
|
import type { TDocumentEmailSettings } from '../../types/document-email';
|
||||||
@@ -107,7 +107,39 @@ export const EnvelopeEditorProvider = ({
|
|||||||
|
|
||||||
const [_searchParams, setSearchParams] = useSearchParams();
|
const [_searchParams, setSearchParams] = useSearchParams();
|
||||||
|
|
||||||
const [envelope, _setEnvelope] = useState(initialEnvelope);
|
/**
|
||||||
|
* The envelope is kept in a ref-backed external store instead of useState so
|
||||||
|
* that async consumers (debounced autosave callbacks, flushAutosave, resetForms)
|
||||||
|
* can synchronously read the latest value via `getEnvelope`.
|
||||||
|
*
|
||||||
|
* React subscribes to the store through useSyncExternalStore, keeping renders in
|
||||||
|
* sync without maintaining a separate copy of the state.
|
||||||
|
*/
|
||||||
|
const envelopeStoreRef = useRef(initialEnvelope);
|
||||||
|
const envelopeStoreSubscribersRef = useRef(new Set<() => void>());
|
||||||
|
|
||||||
|
const subscribeToEnvelopeStore = useCallback((onStoreChange: () => void) => {
|
||||||
|
envelopeStoreSubscribersRef.current.add(onStoreChange);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
envelopeStoreSubscribersRef.current.delete(onStoreChange);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getEnvelope = useCallback(() => envelopeStoreRef.current, []);
|
||||||
|
|
||||||
|
const setEnvelope = useCallback((action: React.SetStateAction<TEditorEnvelope>) => {
|
||||||
|
const next = typeof action === 'function' ? action(envelopeStoreRef.current) : action;
|
||||||
|
|
||||||
|
envelopeStoreRef.current = next;
|
||||||
|
|
||||||
|
for (const onStoreChange of envelopeStoreSubscribersRef.current) {
|
||||||
|
onStoreChange();
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const envelope = useSyncExternalStore(subscribeToEnvelopeStore, getEnvelope, getEnvelope);
|
||||||
|
|
||||||
const [autosaveError, setAutosaveError] = useState<boolean>(false);
|
const [autosaveError, setAutosaveError] = useState<boolean>(false);
|
||||||
|
|
||||||
const isCscMode = IS_INSTANCE_CSC_MODE();
|
const isCscMode = IS_INSTANCE_CSC_MODE();
|
||||||
@@ -135,8 +167,6 @@ export const EnvelopeEditorProvider = ({
|
|||||||
};
|
};
|
||||||
}, [isCscMode, providedEditorConfig]);
|
}, [isCscMode, providedEditorConfig]);
|
||||||
|
|
||||||
const envelopeRef = useRef(initialEnvelope);
|
|
||||||
|
|
||||||
const externalFlushCallbacksRef = useRef<Map<string, () => Promise<void>>>(new Map());
|
const externalFlushCallbacksRef = useRef<Map<string, () => Promise<void>>>(new Map());
|
||||||
const pendingMutationsRef = useRef<Set<Promise<unknown>>>(new Set());
|
const pendingMutationsRef = useRef<Set<Promise<unknown>>>(new Set());
|
||||||
|
|
||||||
@@ -156,14 +186,6 @@ export const EnvelopeEditorProvider = ({
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const setEnvelope: typeof _setEnvelope = (action) => {
|
|
||||||
_setEnvelope((prev) => {
|
|
||||||
const next = typeof action === 'function' ? action(prev) : action;
|
|
||||||
envelopeRef.current = next;
|
|
||||||
return next;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const isEmbedded = editorConfig.embedded !== undefined;
|
const isEmbedded = editorConfig.embedded !== undefined;
|
||||||
|
|
||||||
const editorFields = useEditorFields({
|
const editorFields = useEditorFields({
|
||||||
@@ -192,16 +214,18 @@ export const EnvelopeEditorProvider = ({
|
|||||||
try {
|
try {
|
||||||
let recipients: TEditorEnvelope['recipients'] = [];
|
let recipients: TEditorEnvelope['recipients'] = [];
|
||||||
|
|
||||||
|
const currentEnvelope = getEnvelope();
|
||||||
|
|
||||||
if (!isEmbedded) {
|
if (!isEmbedded) {
|
||||||
const response = await setRecipientsMutation.mutateAsync({
|
const response = await setRecipientsMutation.mutateAsync({
|
||||||
envelopeId: envelope.id,
|
envelopeId: currentEnvelope.id,
|
||||||
envelopeType: envelope.type,
|
envelopeType: currentEnvelope.type,
|
||||||
recipients: localRecipients,
|
recipients: localRecipients,
|
||||||
});
|
});
|
||||||
|
|
||||||
recipients = response.data;
|
recipients = response.data;
|
||||||
} else {
|
} else {
|
||||||
recipients = mapLocalRecipientsToRecipients({ envelope, localRecipients });
|
recipients = mapLocalRecipientsToRecipients({ envelope: currentEnvelope, localRecipients });
|
||||||
}
|
}
|
||||||
|
|
||||||
setEnvelope((prev) => ({
|
setEnvelope((prev) => ({
|
||||||
@@ -211,9 +235,7 @@ export const EnvelopeEditorProvider = ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
// Reset the local fields to ensure deleted recipient fields are removed.
|
// Reset the local fields to ensure deleted recipient fields are removed.
|
||||||
editorFields.resetForm(
|
editorFields.resetForm(getEnvelope().fields);
|
||||||
envelope.fields.filter((field) => recipients.some((recipient) => recipient.id === field.recipientId)),
|
|
||||||
);
|
|
||||||
|
|
||||||
setAutosaveError(false);
|
setAutosaveError(false);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -248,16 +270,18 @@ export const EnvelopeEditorProvider = ({
|
|||||||
try {
|
try {
|
||||||
let fields: TSetEnvelopeFieldsResponse['data'] = [];
|
let fields: TSetEnvelopeFieldsResponse['data'] = [];
|
||||||
|
|
||||||
|
const currentEnvelope = getEnvelope();
|
||||||
|
|
||||||
if (!isEmbedded) {
|
if (!isEmbedded) {
|
||||||
const response = await setFieldsMutation.mutateAsync({
|
const response = await setFieldsMutation.mutateAsync({
|
||||||
envelopeId: envelope.id,
|
envelopeId: currentEnvelope.id,
|
||||||
envelopeType: envelope.type,
|
envelopeType: currentEnvelope.type,
|
||||||
fields: localFields,
|
fields: localFields,
|
||||||
});
|
});
|
||||||
|
|
||||||
fields = response.data;
|
fields = response.data;
|
||||||
} else {
|
} else {
|
||||||
fields = mapLocalFieldsToFields({ envelope, localFields });
|
fields = mapLocalFieldsToFields({ envelope: currentEnvelope, localFields });
|
||||||
}
|
}
|
||||||
|
|
||||||
setEnvelope((prev) => ({
|
setEnvelope((prev) => ({
|
||||||
@@ -309,7 +333,7 @@ export const EnvelopeEditorProvider = ({
|
|||||||
try {
|
try {
|
||||||
const response = !isEmbedded
|
const response = !isEmbedded
|
||||||
? await updateEnvelopeMutation.mutateAsync({
|
? await updateEnvelopeMutation.mutateAsync({
|
||||||
envelopeId: envelope.id,
|
envelopeId: getEnvelope().id,
|
||||||
data,
|
data,
|
||||||
meta,
|
meta,
|
||||||
})
|
})
|
||||||
@@ -467,12 +491,14 @@ export const EnvelopeEditorProvider = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const resetForms = () => {
|
const resetForms = () => {
|
||||||
|
const currentEnvelope = getEnvelope();
|
||||||
|
|
||||||
editorRecipients.resetForm({
|
editorRecipients.resetForm({
|
||||||
recipients: envelopeRef.current.recipients,
|
recipients: currentEnvelope.recipients,
|
||||||
documentMeta: envelopeRef.current.documentMeta,
|
documentMeta: currentEnvelope.documentMeta,
|
||||||
});
|
});
|
||||||
|
|
||||||
editorFields.resetForm(envelopeRef.current.fields);
|
editorFields.resetForm(currentEnvelope.fields);
|
||||||
};
|
};
|
||||||
|
|
||||||
const flushAutosave = async (): Promise<TEditorEnvelope> => {
|
const flushAutosave = async (): Promise<TEditorEnvelope> => {
|
||||||
@@ -488,7 +514,7 @@ export const EnvelopeEditorProvider = ({
|
|||||||
await Promise.allSettled(Array.from(pendingMutationsRef.current));
|
await Promise.allSettled(Array.from(pendingMutationsRef.current));
|
||||||
}
|
}
|
||||||
|
|
||||||
return envelopeRef.current;
|
return getEnvelope();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"postcss-selector-parser": "^7.1.4",
|
"postcss-selector-parser": "^7.1.4",
|
||||||
"posthog-js": "^1.297.2",
|
"posthog-js": "^1.297.2",
|
||||||
"posthog-node": "4.18.0",
|
"posthog-node": "4.18.0",
|
||||||
"react": "^18",
|
"react": "^19.2.7",
|
||||||
"remeda": "^2.32.0",
|
"remeda": "^2.32.0",
|
||||||
"sharp": "0.34.5",
|
"sharp": "0.34.5",
|
||||||
"skia-canvas": "^3.0.8",
|
"skia-canvas": "^3.0.8",
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
"@documenso/prisma": "*",
|
"@documenso/prisma": "*",
|
||||||
"@simplewebauthn/server": "^13.2.2",
|
"@simplewebauthn/server": "^13.2.2",
|
||||||
"@tanstack/react-query": "5.90.10",
|
"@tanstack/react-query": "5.90.10",
|
||||||
"@trpc/client": "11.8.1",
|
"@trpc/client": "11.17.0",
|
||||||
"@trpc/react-query": "11.8.1",
|
"@trpc/react-query": "11.17.0",
|
||||||
"@trpc/server": "11.8.1",
|
"@trpc/server": "11.17.0",
|
||||||
"@ts-rest/core": "^3.52.1",
|
"@ts-rest/core": "^3.52.1",
|
||||||
"formidable": "^3.5.4",
|
"formidable": "^3.5.4",
|
||||||
"luxon": "^3.7.2",
|
"luxon": "^3.7.2",
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export const SigningCard3D = ({ className, name, signature, signingCelebrationIm
|
|||||||
|
|
||||||
const [trackMouse, setTrackMouse] = useState(false);
|
const [trackMouse, setTrackMouse] = useState(false);
|
||||||
|
|
||||||
const timeoutRef = useRef<number | undefined>();
|
const timeoutRef = useRef<number | undefined>(undefined);
|
||||||
|
|
||||||
const cardX = useMotionValue(0);
|
const cardX = useMotionValue(0);
|
||||||
const cardY = useMotionValue(0);
|
const cardY = useMotionValue(0);
|
||||||
|
|||||||
@@ -18,59 +18,32 @@
|
|||||||
"@documenso/tailwind-config": "*",
|
"@documenso/tailwind-config": "*",
|
||||||
"@documenso/tsconfig": "*",
|
"@documenso/tsconfig": "*",
|
||||||
"@types/luxon": "^3.7.1",
|
"@types/luxon": "^3.7.1",
|
||||||
"@types/react": "18.3.27",
|
"@types/react": "^19.2.17",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "^19.2.3",
|
||||||
"react": "^18",
|
"react": "^19.2.7",
|
||||||
"typescript": "5.6.2"
|
"typescript": "5.6.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@documenso/lib": "*",
|
"@documenso/lib": "*",
|
||||||
"@hello-pangea/dnd": "^16.6.0",
|
"@hello-pangea/dnd": "^18.0.1",
|
||||||
"@hookform/resolvers": "^3",
|
"@hookform/resolvers": "^3",
|
||||||
"@lingui/macro": "^5.6.0",
|
"@lingui/macro": "^5.6.0",
|
||||||
"@lingui/react": "^5.6.0",
|
"@lingui/react": "^5.6.0",
|
||||||
"@radix-ui/react-accordion": "^1.2.12",
|
|
||||||
"@radix-ui/react-alert-dialog": "^1.1.15",
|
|
||||||
"@radix-ui/react-aspect-ratio": "^1.1.8",
|
|
||||||
"@radix-ui/react-avatar": "^1.1.11",
|
|
||||||
"@radix-ui/react-checkbox": "^1.3.3",
|
|
||||||
"@radix-ui/react-collapsible": "^1.1.12",
|
|
||||||
"@radix-ui/react-context-menu": "^2.2.16",
|
|
||||||
"@radix-ui/react-dialog": "^1.1.15",
|
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
||||||
"@radix-ui/react-hover-card": "^1.1.15",
|
|
||||||
"@radix-ui/react-label": "^2.1.8",
|
|
||||||
"@radix-ui/react-menubar": "^1.1.16",
|
|
||||||
"@radix-ui/react-navigation-menu": "^1.2.14",
|
|
||||||
"@radix-ui/react-popover": "^1.1.15",
|
|
||||||
"@radix-ui/react-progress": "^1.1.8",
|
|
||||||
"@radix-ui/react-radio-group": "^1.3.8",
|
|
||||||
"@radix-ui/react-scroll-area": "^1.2.10",
|
|
||||||
"@radix-ui/react-select": "^2.2.6",
|
|
||||||
"@radix-ui/react-separator": "^1.1.8",
|
|
||||||
"@radix-ui/react-slider": "^1.3.6",
|
|
||||||
"@radix-ui/react-slot": "^1.2.4",
|
|
||||||
"@radix-ui/react-switch": "^1.2.6",
|
|
||||||
"@radix-ui/react-tabs": "^1.1.13",
|
|
||||||
"@radix-ui/react-toast": "^1.2.15",
|
|
||||||
"@radix-ui/react-toggle": "^1.1.10",
|
|
||||||
"@radix-ui/react-toggle-group": "^1.1.11",
|
|
||||||
"@radix-ui/react-tooltip": "^1.2.8",
|
|
||||||
"@scure/base": "^1.2.6",
|
"@scure/base": "^1.2.6",
|
||||||
"@tanstack/react-table": "^8.21.3",
|
"@tanstack/react-table": "^8.21.3",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"cmdk": "^0.2.1",
|
"cmdk": "^1.1.1",
|
||||||
"colord": "^2.9.3",
|
"colord": "^2.9.3",
|
||||||
"framer-motion": "^12.23.24",
|
"framer-motion": "^12.23.24",
|
||||||
"lucide-react": "^0.554.0",
|
"lucide-react": "^0.554.0",
|
||||||
"luxon": "^3.7.2",
|
"luxon": "^3.7.2",
|
||||||
"pdfjs-dist": "5.4.296",
|
"pdfjs-dist": "5.4.296",
|
||||||
"perfect-freehand": "^1.2.2",
|
"perfect-freehand": "^1.2.2",
|
||||||
"react": "^18",
|
"react": "^19.2.7",
|
||||||
"react-colorful": "^5.6.1",
|
"react-colorful": "^5.6.1",
|
||||||
"react-day-picker": "^8.10.1",
|
"react-day-picker": "^8.10.1",
|
||||||
"react-dom": "^18",
|
"react-dom": "^19.2.7",
|
||||||
"react-hook-form": "^7.66.1",
|
"react-hook-form": "^7.66.1",
|
||||||
"react-rnd": "^10.5.2",
|
"react-rnd": "^10.5.2",
|
||||||
"remeda": "^2.32.0",
|
"remeda": "^2.32.0",
|
||||||
|
|||||||
@@ -145,7 +145,9 @@ const CommandItem = React.forwardRef<
|
|||||||
<CommandPrimitive.Item
|
<CommandPrimitive.Item
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
// cmdk 1.x always renders data-disabled="true|false", so the variant must
|
||||||
|
// check the value (bare data-[disabled] matches attribute presence).
|
||||||
|
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -103,15 +103,10 @@ export const FieldContent = ({ field, documentMeta }: FieldIconProps) => {
|
|||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-y-2 py-0.5">
|
<div className="flex flex-col gap-y-2 py-0.5">
|
||||||
<RadioGroup className="gap-y-1">
|
<RadioGroup value={field.customText ?? ''} className="gap-y-1">
|
||||||
{field.fieldMeta.values.map((item, index) => (
|
{field.fieldMeta.values.map((item, index) => (
|
||||||
<div key={index} className="flex items-center">
|
<div key={index} className="flex items-center">
|
||||||
<RadioGroupItem
|
<RadioGroupItem className="pointer-events-none h-3 w-3" value={item.value} id={`option-${index}`} />
|
||||||
className="pointer-events-none h-3 w-3"
|
|
||||||
value={item.value}
|
|
||||||
id={`option-${index}`}
|
|
||||||
checked={item.value === field.customText}
|
|
||||||
/>
|
|
||||||
{item.value && (
|
{item.value && (
|
||||||
<Label htmlFor={`option-${index}`} className="ml-1.5 font-normal text-foreground text-xs">
|
<Label htmlFor={`option-${index}`} className="ml-1.5 font-normal text-foreground text-xs">
|
||||||
{item.value}
|
{item.value}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { RecipientRole } from '@prisma/client';
|
import type { RecipientRole } from '@prisma/client';
|
||||||
import { BadgeCheck, Copy, Eye, PencilLine, User } from 'lucide-react';
|
import { BadgeCheck, Copy, Eye, PencilLine, User } from 'lucide-react';
|
||||||
|
import type { JSX } from 'react';
|
||||||
|
|
||||||
export const ROLE_ICONS: Record<RecipientRole, JSX.Element> = {
|
export const ROLE_ICONS: Record<RecipientRole, JSX.Element> = {
|
||||||
SIGNER: <PencilLine className="h-4 w-4" />,
|
SIGNER: <PencilLine className="h-4 w-4" />,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { getSvgPathFromStroke } from './helper';
|
|||||||
import { Point } from './point';
|
import { Point } from './point';
|
||||||
import { SignaturePadColorPicker } from './signature-pad-color-picker';
|
import { SignaturePadColorPicker } from './signature-pad-color-picker';
|
||||||
|
|
||||||
const checkSignatureValidity = (element: RefObject<HTMLCanvasElement>) => {
|
const checkSignatureValidity = (element: RefObject<HTMLCanvasElement | null>) => {
|
||||||
if (!element.current) {
|
if (!element.current) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user