Compare commits

..
6 changed files with 48 additions and 28 deletions
@@ -49,7 +49,7 @@ Use the `cssVars` prop on any embed component to override default colors, spacin
| `widgetForeground` | Widget text color |
| `border` | Default border color |
| `input` | Input field border color |
| `primary` | Primary action/button color. The loading spinner on fields also uses this color. |
| `primary` | Primary action/button color |
| `primaryForeground` | Primary action/button text color |
| `secondary` | Secondary action/button color |
| `secondaryForeground` | Secondary button text color |
@@ -12,11 +12,20 @@ import { cn } from '@documenso/ui/lib/utils';
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@documenso/ui/primitives/accordion';
import { Button } from '@documenso/ui/primitives/button';
import { ColorPicker } from '@documenso/ui/primitives/color-picker';
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel } from '@documenso/ui/primitives/form/form';
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@documenso/ui/primitives/form/form';
import { Input } from '@documenso/ui/primitives/input';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@documenso/ui/primitives/select';
import { Textarea } from '@documenso/ui/primitives/textarea';
import { zodResolver } from '@hookform/resolvers/zod';
import { msg } from '@lingui/core/macro';
import { Trans, useLingui } from '@lingui/react/macro';
import type { TeamGlobalSettings } from '@prisma/client';
import { Loader } from 'lucide-react';
@@ -37,14 +46,17 @@ const ZBrandingPreferencesFormSchema = z.object({
.instanceof(File)
.refine(
(file) => file.size <= BRANDING_LOGO_MAX_SIZE_BYTES,
`File size must be less than ${BRANDING_LOGO_MAX_SIZE_MB}MB`,
msg`File size must be less than ${BRANDING_LOGO_MAX_SIZE_MB}MB`,
)
.refine(
(file) => BRANDING_LOGO_ALLOWED_TYPES.includes(file.type),
msg`Only .jpg, .png, and .webp files are accepted`,
)
.refine((file) => BRANDING_LOGO_ALLOWED_TYPES.includes(file.type), 'Only .jpg, .png, and .webp files are accepted')
.nullish(),
brandingUrl: z.string().url().optional().or(z.literal('')),
brandingCompanyDetails: z.string().max(500).optional(),
brandingUrl: z.string().url(msg`Please enter a valid URL`).optional().or(z.literal('')),
brandingCompanyDetails: z.string().max(500, msg`Brand details must be less than 500 characters`).optional(),
brandingColors: ZCssVarsSchema.default({}),
brandingCss: z.string().max(10_000).default(''),
brandingCss: z.string().max(10_000, msg`Custom CSS must be less than 10,000 characters`).default(''),
});
export type TBrandingPreferencesFormSchema = z.infer<typeof ZBrandingPreferencesFormSchema>;
@@ -349,6 +361,8 @@ export function BrandingPreferencesForm({
</span>
)}
</FormDescription>
<FormMessage />
</div>
</InheritableField>
)}
@@ -379,6 +393,8 @@ export function BrandingPreferencesForm({
</span>
)}
</FormDescription>
<FormMessage />
</InheritableField>
)}
/>
@@ -413,6 +429,8 @@ export function BrandingPreferencesForm({
</span>
)}
</FormDescription>
<FormMessage />
</InheritableField>
)}
/>
@@ -597,6 +615,8 @@ export function BrandingPreferencesForm({
<FormDescription>
<Trans>Border radius size in REM units (e.g. 0.5rem).</Trans>
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
@@ -634,6 +654,8 @@ export function BrandingPreferencesForm({
shown after you save.
</Trans>
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
@@ -51,6 +51,12 @@ export async function rejectDocumentWithToken({ token, id, reason, requestMetada
});
}
if (recipient.signingStatus !== SigningStatus.NOT_SIGNED) {
throw new AppError(AppErrorCode.INVALID_REQUEST, {
message: `Recipient ${recipient.id} has already actioned this document`,
});
}
assertRecipientNotExpired(recipient);
// Update the recipient status to rejected
@@ -166,19 +166,3 @@ export const resolveFieldCanvasStyle = (
return style;
};
/**
* Resolve the `--primary` color from the same cascade as the fields, so canvas
* elements such as the loading spinner follow team and embed branding.
*/
export const resolvePrimaryColor = () => {
const $anchor = document.querySelector(FIELD_PROBE_ANCHOR_SELECTOR);
if (!$anchor) {
return undefined;
}
const color = colord(`hsl(${window.getComputedStyle($anchor).getPropertyValue('--primary')})`);
return color.isValid() ? color.toRgbString() : undefined;
};
@@ -1,7 +1,6 @@
import { DEFAULT_RECT_BACKGROUND, getRecipientColorStyles } from '@documenso/ui/lib/recipient-colors';
import Konva from 'konva';
import { resolvePrimaryColor } from './field-canvas-style';
import type { FieldToRender, RenderFieldElementOptions } from './field-renderer';
import { calculateFieldPosition } from './field-renderer';
@@ -95,7 +94,7 @@ export const createSpinner = ({ fieldWidth, fieldHeight }: { fieldWidth: number;
outerRadius: spinnerSize / 2,
angle: 270,
rotation: 0,
fill: resolvePrimaryColor() ?? 'rgba(122, 195, 85, 1)',
fill: 'rgba(122, 195, 85, 1)',
lineCap: 'round',
});
@@ -41,6 +41,15 @@ export const SignaturePadDialog = ({
const [showSignatureModal, setShowSignatureModal] = useState(false);
const [signature, setSignature] = useState<string>(value ?? '');
const onOpenChange = (open: boolean) => {
if (disabled) {
return;
}
setSignature(value ?? '');
setShowSignatureModal(open);
};
return (
<div
className={cn(
@@ -62,7 +71,7 @@ export const SignaturePadDialog = ({
type="button"
disabled={disabled}
className="absolute inset-0 flex items-center justify-center bg-transparent"
onClick={() => setShowSignatureModal(true)}
onClick={() => onOpenChange(true)}
whileHover="onHover"
>
{!value && !disableAnimation && (
@@ -109,7 +118,7 @@ export const SignaturePadDialog = ({
)}
</motion.button>
<Dialog open={showSignatureModal} onOpenChange={disabled ? undefined : setShowSignatureModal}>
<Dialog open={showSignatureModal} onOpenChange={onOpenChange}>
<DialogContent hideClose={true} className="p-6 pt-4">
<SignaturePad
id="signature"
@@ -135,7 +144,7 @@ export const SignaturePadDialog = ({
disabled={!signature}
onClick={() => {
onChange(signature);
setShowSignatureModal(false);
onOpenChange(false);
}}
>
{dialogConfirmText ? parseMessageDescriptor(i18n._, dialogConfirmText) : <Trans>Next</Trans>}