mirror of
https://github.com/documenso/documenso
synced 2026-04-21 13:27:18 +00:00
refactor: avoid recipient color duplication (#2355)
This commit is contained in:
parent
1ee6ec87a2
commit
83fbc70a1c
16 changed files with 128 additions and 220 deletions
|
|
@ -16,7 +16,7 @@ import { type TFieldMetaSchema, ZFieldMetaSchema } from '@documenso/lib/types/fi
|
|||
import { nanoid } from '@documenso/lib/universal/id';
|
||||
import { ADVANCED_FIELD_TYPES_WITH_OPTIONAL_SETTING } from '@documenso/lib/utils/advanced-fields-helpers';
|
||||
import { getDocumentDataUrlForPdfViewer } from '@documenso/lib/utils/envelope-download';
|
||||
import { useRecipientColors } from '@documenso/ui/lib/recipient-colors';
|
||||
import { getRecipientColorStyles } from '@documenso/ui/lib/recipient-colors';
|
||||
import { cn } from '@documenso/ui/lib/utils';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { FieldItem } from '@documenso/ui/primitives/document-flow/field-item';
|
||||
|
|
@ -155,9 +155,7 @@ export const ConfigureFieldsView = ({
|
|||
});
|
||||
|
||||
const selectedRecipientIndex = recipients.findIndex((r) => r.id === selectedRecipient?.id);
|
||||
const selectedRecipientStyles = useRecipientColors(
|
||||
selectedRecipientIndex === -1 ? 0 : selectedRecipientIndex,
|
||||
);
|
||||
const selectedRecipientStyles = getRecipientColorStyles(selectedRecipientIndex);
|
||||
|
||||
const form = useForm<TConfigureFieldsFormSchema>({
|
||||
defaultValues: {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { type TRecipientActionAuth } from '@documenso/lib/types/document-auth';
|
|||
import { ZFieldMetaSchema } from '@documenso/lib/types/field-meta';
|
||||
import type { FieldWithSignature } from '@documenso/prisma/types/field-with-signature';
|
||||
import { FieldRootContainer } from '@documenso/ui/components/field/field';
|
||||
import { RECIPIENT_COLOR_STYLES } from '@documenso/ui/lib/recipient-colors';
|
||||
import { getRecipientColorStyles } from '@documenso/ui/lib/recipient-colors';
|
||||
import { cn } from '@documenso/ui/lib/utils';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip';
|
||||
|
||||
|
|
@ -131,18 +131,16 @@ export const DocumentSigningFieldContainer = ({
|
|||
|
||||
return (
|
||||
<FieldRootContainer
|
||||
color={
|
||||
field.fieldMeta?.readOnly ? RECIPIENT_COLOR_STYLES.readOnly : RECIPIENT_COLOR_STYLES.green
|
||||
}
|
||||
field={field}
|
||||
>
|
||||
{!field.inserted && !loading && !readOnlyField && (
|
||||
<button
|
||||
type="submit"
|
||||
className="absolute inset-0 z-10 h-full w-full rounded-[2px]"
|
||||
onClick={async () => handleInsertField()}
|
||||
/>
|
||||
)}
|
||||
color={getRecipientColorStyles(field.fieldMeta?.readOnly ? 'readOnly' : 0)}
|
||||
field={field}
|
||||
>
|
||||
{!field.inserted && !loading && !readOnlyField && (
|
||||
<button
|
||||
type="submit"
|
||||
className="absolute inset-0 z-10 h-full w-full rounded-[2px]"
|
||||
onClick={async () => handleInsertField()}
|
||||
/>
|
||||
)}
|
||||
|
||||
{type === 'Checkbox' && field.inserted && !loading && !readOnlyField && (
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import { FIELD_META_DEFAULT_VALUES } from '@documenso/lib/types/field-meta';
|
|||
import { nanoid } from '@documenso/lib/universal/id';
|
||||
import { canRecipientFieldsBeModified } from '@documenso/lib/utils/recipients';
|
||||
import { SignatureIcon } from '@documenso/ui/icons/signature';
|
||||
import { RECIPIENT_COLOR_STYLES } from '@documenso/ui/lib/recipient-colors';
|
||||
import { getRecipientColorStyles } from '@documenso/ui/lib/recipient-colors';
|
||||
import { cn } from '@documenso/ui/lib/utils';
|
||||
import { FRIENDLY_FIELD_TYPE } from '@documenso/ui/primitives/document-flow/types';
|
||||
|
||||
|
|
@ -253,9 +253,10 @@ export const EnvelopeEditorFieldDragDrop = ({
|
|||
};
|
||||
}, [onMouseClick, onMouseMove, selectedField]);
|
||||
|
||||
const selectedRecipientColor = useMemo(() => {
|
||||
return selectedRecipientId ? getRecipientColorKey(selectedRecipientId) : 'green';
|
||||
}, [selectedRecipientId, getRecipientColorKey]);
|
||||
const selectedRecipientStyles = useMemo(
|
||||
() => getRecipientColorStyles(getRecipientColorKey(selectedRecipientId ?? -1)),
|
||||
[selectedRecipientId, getRecipientColorKey],
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -270,21 +271,14 @@ export const EnvelopeEditorFieldDragDrop = ({
|
|||
data-selected={selectedField === field.type ? true : undefined}
|
||||
className={cn(
|
||||
'group flex h-12 cursor-pointer items-center justify-center rounded-lg border border-border px-4 transition-colors',
|
||||
RECIPIENT_COLOR_STYLES[selectedRecipientColor].fieldButton,
|
||||
selectedRecipientStyles.fieldButton,
|
||||
)}
|
||||
>
|
||||
<p
|
||||
className={cn(
|
||||
'flex items-center justify-center gap-x-1.5 font-noto text-sm font-normal text-muted-foreground group-data-[selected]:text-foreground',
|
||||
field.className,
|
||||
{
|
||||
'group-hover:text-recipient-green': selectedRecipientColor === 'green',
|
||||
'group-hover:text-recipient-blue': selectedRecipientColor === 'blue',
|
||||
'group-hover:text-recipient-purple': selectedRecipientColor === 'purple',
|
||||
'group-hover:text-recipient-orange': selectedRecipientColor === 'orange',
|
||||
'group-hover:text-recipient-yellow': selectedRecipientColor === 'yellow',
|
||||
'group-hover:text-recipient-pink': selectedRecipientColor === 'pink',
|
||||
},
|
||||
selectedRecipientStyles.fieldButtonText,
|
||||
)}
|
||||
>
|
||||
{field.type !== FieldType.SIGNATURE && <field.icon className="h-4 w-4" />}
|
||||
|
|
@ -298,7 +292,7 @@ export const EnvelopeEditorFieldDragDrop = ({
|
|||
<div
|
||||
className={cn(
|
||||
'dark:text-muted-background pointer-events-none fixed z-50 flex cursor-pointer flex-col items-center justify-center rounded-[2px] bg-white font-noto text-muted-foreground ring-2 transition duration-200 [container-type:size]',
|
||||
RECIPIENT_COLOR_STYLES[selectedRecipientColor].base,
|
||||
selectedRecipientStyles.base,
|
||||
selectedField === FieldType.SIGNATURE && 'font-signature',
|
||||
{
|
||||
'-rotate-6 scale-90 opacity-50 dark:bg-black/20': !isFieldWithinBounds,
|
||||
|
|
|
|||
|
|
@ -59,12 +59,8 @@ export const EnvelopeRecipientSelector = ({
|
|||
role="combobox"
|
||||
className={cn(
|
||||
'justify-between bg-background font-normal text-muted-foreground hover:text-foreground',
|
||||
getRecipientColorStyles(
|
||||
Math.max(
|
||||
recipients.findIndex((r) => r.id === selectedRecipient?.id),
|
||||
0,
|
||||
),
|
||||
).comboxBoxTrigger,
|
||||
getRecipientColorStyles(recipients.findIndex((r) => r.id === selectedRecipient?.id))
|
||||
.comboBoxTrigger,
|
||||
className,
|
||||
)}
|
||||
>
|
||||
|
|
@ -197,12 +193,8 @@ export const EnvelopeRecipientSelectorCommand = ({
|
|||
key={recipient.id}
|
||||
className={cn(
|
||||
'px-2 last:mb-1 [&:not(:first-child)]:mt-1',
|
||||
getRecipientColorStyles(
|
||||
Math.max(
|
||||
recipients.findIndex((r) => r.id === recipient.id),
|
||||
0,
|
||||
),
|
||||
).comboxBoxItem,
|
||||
getRecipientColorStyles(recipients.findIndex((r) => r.id === recipient.id))
|
||||
.comboBoxItem,
|
||||
{
|
||||
'text-muted-foreground': recipient.sendStatus === SendStatus.SENT,
|
||||
'cursor-not-allowed': isRecipientDisabled(recipient.id),
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ import { extractInitials } from '@documenso/lib/utils/recipient-formatter';
|
|||
import type { TSignEnvelopeFieldValue } from '@documenso/trpc/server/envelope-router/sign-envelope-field.types';
|
||||
import { EnvelopeRecipientFieldTooltip } from '@documenso/ui/components/document/envelope-recipient-field-tooltip';
|
||||
import { EnvelopeFieldToolTip } from '@documenso/ui/components/field/envelope-field-tooltip';
|
||||
import type { TRecipientColor } from '@documenso/ui/lib/recipient-colors';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
import { useEmbedSigningContext } from '~/components/embed/embed-signing-context';
|
||||
|
|
@ -139,13 +138,11 @@ export const EnvelopeSignerPageRenderer = ({ pageData }: { pageData: PageRenderD
|
|||
|
||||
const fieldToRender = ZFullFieldSchema.parse(unparsedField);
|
||||
|
||||
let color: TRecipientColor = 'green';
|
||||
|
||||
if (fieldToRender.fieldMeta?.readOnly) {
|
||||
color = 'readOnly';
|
||||
} else if (showPendingFieldTooltip && isFieldUnsignedAndRequired(fieldToRender)) {
|
||||
color = 'orange';
|
||||
}
|
||||
const color = fieldToRender.fieldMeta?.readOnly
|
||||
? 'readOnly'
|
||||
: showPendingFieldTooltip && isFieldUnsignedAndRequired(fieldToRender)
|
||||
? 'orange'
|
||||
: 'green';
|
||||
|
||||
const { fieldGroup } = renderField({
|
||||
scale,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const baseConfig = require('@documenso/tailwind-config');
|
||||
const baseConfig = require('@documenso/ui/tailwind.config.cjs');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
...baseConfig,
|
||||
presets: [baseConfig],
|
||||
content: [
|
||||
...baseConfig.content,
|
||||
'./app/**/*.{ts,tsx}',
|
||||
`${path.join(require.resolve('@documenso/ui'), '..')}/components/**/*.{ts,tsx}`,
|
||||
`${path.join(require.resolve('@documenso/ui'), '..')}/icons/**/*.{ts,tsx}`,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import type { TSetEnvelopeFieldsResponse } from '@documenso/trpc/server/envelope
|
|||
import type { TSetEnvelopeRecipientsRequest } from '@documenso/trpc/server/envelope-router/set-envelope-recipients.types';
|
||||
import type { TUpdateEnvelopeRequest } from '@documenso/trpc/server/envelope-router/update-envelope.types';
|
||||
import type { TRecipientColor } from '@documenso/ui/lib/recipient-colors';
|
||||
import { AVAILABLE_RECIPIENT_COLORS } from '@documenso/ui/lib/recipient-colors';
|
||||
import { getRecipientColor } from '@documenso/ui/lib/recipient-colors';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
import type { TDocumentEmailSettings } from '../../types/document-email';
|
||||
|
|
@ -346,15 +346,8 @@ export const EnvelopeEditorProvider = ({
|
|||
};
|
||||
|
||||
const getRecipientColorKey = useCallback(
|
||||
(recipientId: number) => {
|
||||
const recipientIndex = envelope.recipients.findIndex(
|
||||
(recipient) => recipient.id === recipientId,
|
||||
);
|
||||
|
||||
return AVAILABLE_RECIPIENT_COLORS[
|
||||
Math.max(recipientIndex, 0) % AVAILABLE_RECIPIENT_COLORS.length
|
||||
];
|
||||
},
|
||||
(recipientId: number) =>
|
||||
getRecipientColor(envelope.recipients.findIndex((r) => r.id === recipientId)),
|
||||
[envelope.recipients],
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { type Field, type Recipient } from '@prisma/client';
|
|||
import type { DocumentDataVersion } from '@documenso/lib/types/document';
|
||||
import { getDocumentDataUrl } from '@documenso/lib/utils/envelope-download';
|
||||
import type { TRecipientColor } from '@documenso/ui/lib/recipient-colors';
|
||||
import { AVAILABLE_RECIPIENT_COLORS } from '@documenso/ui/lib/recipient-colors';
|
||||
import { getRecipientColor } from '@documenso/ui/lib/recipient-colors';
|
||||
|
||||
import type { TEnvelope } from '../../types/envelope';
|
||||
import type { FieldRenderMode } from '../../universal/field-renderer/render-field';
|
||||
|
|
@ -198,13 +198,7 @@ export const EnvelopeRenderProvider = ({
|
|||
);
|
||||
|
||||
const getRecipientColorKey = useCallback(
|
||||
(recipientId: number) => {
|
||||
const recipientIndex = recipientIds.findIndex((id) => id === recipientId);
|
||||
|
||||
return AVAILABLE_RECIPIENT_COLORS[
|
||||
Math.max(recipientIndex, 0) % AVAILABLE_RECIPIENT_COLORS.length
|
||||
];
|
||||
},
|
||||
(recipientId: number) => getRecipientColor(recipientIds.findIndex((id) => id === recipientId)),
|
||||
[recipientIds],
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import Konva from 'konva';
|
|||
|
||||
import {
|
||||
DEFAULT_RECT_BACKGROUND,
|
||||
RECIPIENT_COLOR_STYLES,
|
||||
getRecipientColorStyles,
|
||||
} from '@documenso/ui/lib/recipient-colors';
|
||||
|
||||
import type { FieldToRender, RenderFieldElementOptions } from './field-renderer';
|
||||
|
|
@ -70,7 +70,7 @@ export const upsertFieldRect = (
|
|||
width: fieldWidth,
|
||||
height: fieldHeight,
|
||||
fill: DEFAULT_RECT_BACKGROUND,
|
||||
stroke: color ? RECIPIENT_COLOR_STYLES[color].baseRing : '#e5e7eb',
|
||||
stroke: color ? getRecipientColorStyles(color).baseRing : '#e5e7eb',
|
||||
strokeWidth: 2,
|
||||
cornerRadius: 2,
|
||||
strokeScaleEnabled: false,
|
||||
|
|
@ -150,7 +150,7 @@ export const createFieldHoverInteraction = ({
|
|||
return;
|
||||
}
|
||||
|
||||
const hoverColor = RECIPIENT_COLOR_STYLES[options.color].baseRingHover;
|
||||
const hoverColor = getRecipientColorStyles(options.color).baseRingHover;
|
||||
|
||||
fieldGroup.on('mouseover', () => {
|
||||
const layer = fieldRect.getLayer();
|
||||
|
|
|
|||
|
|
@ -110,10 +110,7 @@ export const DocumentReadOnlyFields = ({
|
|||
color={
|
||||
showRecipientColors
|
||||
? getRecipientColorStyles(
|
||||
Math.max(
|
||||
recipientIds.findIndex((id) => id === field.recipientId),
|
||||
0,
|
||||
),
|
||||
recipientIds.findIndex((id) => id === field.recipientId),
|
||||
)
|
||||
: undefined
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
// !: We declare all of our classes here since TailwindCSS will remove any unused CSS classes,
|
||||
// !: therefore doing this at runtime is not possible without whitelisting a set of classnames.
|
||||
// !:
|
||||
// !: This will later be improved as we move to a CSS variable approach and rotate the lightness
|
||||
import { colord } from 'colord';
|
||||
import { once } from 'remeda';
|
||||
|
||||
export type RecipientColorMap = Record<number, RecipientColorStyles>;
|
||||
export type TRecipientColor = 'readOnly' | (typeof AVAILABLE_RECIPIENT_COLORS)[number];
|
||||
|
||||
export type RecipientColorStyles = {
|
||||
base: string;
|
||||
|
|
@ -11,128 +9,89 @@ export type RecipientColorStyles = {
|
|||
baseRingHover: string;
|
||||
baseTextHover: string;
|
||||
fieldButton: string;
|
||||
fieldButtonText: string;
|
||||
fieldItem: string;
|
||||
fieldItemInitials: string;
|
||||
comboxBoxTrigger: string;
|
||||
comboxBoxItem: string;
|
||||
comboBoxTrigger: string;
|
||||
comboBoxItem: string;
|
||||
};
|
||||
|
||||
export const DEFAULT_RECT_BACKGROUND = 'rgba(255, 255, 255, 0.95)';
|
||||
|
||||
// !: values of the declared variable to do all the background, border and shadow styles.
|
||||
export const RECIPIENT_COLOR_STYLES = {
|
||||
readOnly: {
|
||||
const RECIPIENT_COLOR_STYLES: Record<TRecipientColor, () => RecipientColorStyles> = {
|
||||
readOnly: (): RecipientColorStyles => ({
|
||||
base: 'ring-neutral-400',
|
||||
baseRing: 'rgba(176, 176, 176, 1)',
|
||||
baseRingHover: 'rgba(176, 176, 176, 1)',
|
||||
baseTextHover: 'rgba(176, 176, 176, 1)',
|
||||
fieldButton: 'border-neutral-400 hover:border-neutral-400',
|
||||
fieldButtonText: '',
|
||||
fieldItem: 'group/field-item rounded-[2px]',
|
||||
fieldItemInitials: '',
|
||||
comboxBoxTrigger:
|
||||
comboBoxTrigger:
|
||||
'ring-2 ring-recipient-green shadow-[0_0_0_5px_hsl(var(--recipient-green)/10%),0_0_0_2px_hsl(var(--recipient-green)/60%),0_0_0_0.5px_hsl(var(--recipient-green))]',
|
||||
comboxBoxItem: '',
|
||||
},
|
||||
|
||||
green: {
|
||||
base: 'ring-recipient-green hover:bg-recipient-green/30',
|
||||
baseRing: 'rgba(122, 195, 85, 1)',
|
||||
baseRingHover: 'rgba(122, 195, 85, 0.3)',
|
||||
baseTextHover: 'rgba(122, 195, 85, 1)',
|
||||
fieldButton: 'hover:border-recipient-green hover:bg-recipient-green/30 ',
|
||||
fieldItem: 'group/field-item rounded-[2px]',
|
||||
fieldItemInitials: 'group-hover/field-item:bg-recipient-green',
|
||||
comboxBoxTrigger:
|
||||
'ring-2 ring-recipient-green hover:bg-recipient-green/15 active:bg-recipient-green/15 shadow-[0_0_0_5px_hsl(var(--recipient-green)/10%),0_0_0_2px_hsl(var(--recipient-green)/60%),0_0_0_0.5px_hsl(var(--recipient-green))]',
|
||||
comboxBoxItem: 'hover:bg-recipient-green/15 active:bg-recipient-green/15',
|
||||
},
|
||||
|
||||
blue: {
|
||||
base: 'ring-recipient-blue hover:bg-recipient-blue/30',
|
||||
baseRing: 'rgba(56, 123, 199, 1)',
|
||||
baseRingHover: 'rgba(56, 123, 199, 0.3)',
|
||||
baseTextHover: 'rgba(56, 123, 199, 1)',
|
||||
fieldButton: 'hover:border-recipient-blue hover:bg-recipient-blue/30',
|
||||
fieldItem: 'group/field-item rounded-[2px]',
|
||||
fieldItemInitials: 'group-hover/field-item:bg-recipient-blue',
|
||||
comboxBoxTrigger:
|
||||
'ring-2 ring-recipient-blue hover:bg-recipient-blue/15 active:bg-recipient-blue/15 shadow-[0_0_0_5px_hsl(var(--recipient-blue)/10%),0_0_0_2px_hsl(var(--recipient-blue)/60%),0_0_0_0.5px_hsl(var(--recipient-blue))]',
|
||||
comboxBoxItem: 'ring-recipient-blue hover:bg-recipient-blue/15 active:bg-recipient-blue/15',
|
||||
},
|
||||
|
||||
purple: {
|
||||
base: 'ring-recipient-purple hover:bg-recipient-purple/30',
|
||||
baseRing: 'rgba(151, 71, 255, 1)',
|
||||
baseRingHover: 'rgba(151, 71, 255, 0.3)',
|
||||
baseTextHover: 'rgba(151, 71, 255, 1)',
|
||||
fieldButton: 'hover:border-recipient-purple hover:bg-recipient-purple/30',
|
||||
fieldItem: 'group/field-item rounded-[2px]',
|
||||
fieldItemInitials: 'group-hover/field-item:bg-recipient-purple',
|
||||
comboxBoxTrigger:
|
||||
'ring-2 ring-recipient-purple hover:bg-recipient-purple/15 active:bg-recipient-purple/15 shadow-[0_0_0_5px_hsl(var(--recipient-purple)/10%),0_0_0_2px_hsl(var(--recipient-purple)/60%),0_0_0_0.5px_hsl(var(--recipient-purple))]',
|
||||
comboxBoxItem: 'hover:bg-recipient-purple/15 active:bg-recipient-purple/15',
|
||||
},
|
||||
|
||||
orange: {
|
||||
base: 'ring-recipient-orange hover:bg-recipient-orange/30',
|
||||
baseRing: 'rgba(246, 159, 30, 1)',
|
||||
baseRingHover: 'rgba(246, 159, 30, 0.3)',
|
||||
baseTextHover: 'rgba(246, 159, 30, 1)',
|
||||
fieldButton: 'hover:border-recipient-orange hover:bg-recipient-orange/30',
|
||||
fieldItem: 'group/field-item rounded-[2px]',
|
||||
fieldItemInitials: 'group-hover/field-item:bg-recipient-orange',
|
||||
comboxBoxTrigger:
|
||||
'ring-2 ring-recipient-orange hover:bg-recipient-orange/15 active:bg-recipient-orange/15 shadow-[0_0_0_5px_hsl(var(--recipient-orange)/10%),0_0_0_2px_hsl(var(--recipient-orange)/60%),0_0_0_0.5px_hsl(var(--recipient-orange))]',
|
||||
comboxBoxItem: 'hover:bg-recipient-orange/15 active:bg-recipient-orange/15',
|
||||
},
|
||||
|
||||
yellow: {
|
||||
base: 'ring-recipient-yellow hover:bg-recipient-yellow/30',
|
||||
baseRing: 'rgba(219, 186, 0, 1)',
|
||||
baseRingHover: 'rgba(219, 186, 0, 0.3)',
|
||||
baseTextHover: 'rgba(219, 186, 0, 1)',
|
||||
fieldButton: 'hover:border-recipient-yellow hover:bg-recipient-yellow/30',
|
||||
fieldItem: 'group/field-item rounded-[2px]',
|
||||
fieldItemInitials: 'group-hover/field-item:bg-recipient-yellow',
|
||||
comboxBoxTrigger:
|
||||
'ring-2 ring-recipient-yellow hover:bg-recipient-yellow/15 active:bg-recipient-yellow/15 shadow-[0_0_0_5px_hsl(var(--recipient-yellow)/10%),0_0_0_2px_hsl(var(--recipient-yellow)/60%),0_0_0_0.5px_hsl(var(--recipient-yellow))]',
|
||||
comboxBoxItem: 'hover:bg-recipient-yellow/15 active:bg-recipient-yellow/15',
|
||||
},
|
||||
|
||||
pink: {
|
||||
base: 'ring-recipient-pink hover:bg-recipient-pink/30',
|
||||
baseRing: 'rgba(217, 74, 186, 1)',
|
||||
baseRingHover: 'rgba(217, 74, 186, 0.3)',
|
||||
baseTextHover: 'rgba(217, 74, 186, 1)',
|
||||
fieldButton: 'hover:border-recipient-pink hover:bg-recipient-pink/30',
|
||||
fieldItem: 'group/field-item rounded-[2px]',
|
||||
fieldItemInitials: 'group-hover/field-item:bg-recipient-pink',
|
||||
comboxBoxTrigger:
|
||||
'ring-2 ring-recipient-pink hover:bg-recipient-pink/15 active:bg-recipient-pink/15 shadow-[0_0_0_5px_hsl(var(--recipient-pink)/10%),0_0_0_2px_hsl(var(--recipient-pink)/60%),0_0_0_0.5px_hsl(var(--recipient-pink',
|
||||
comboxBoxItem: 'hover:bg-recipient-pink/15 active:bg-recipient-pink/15',
|
||||
},
|
||||
} satisfies Record<string, RecipientColorStyles>;
|
||||
|
||||
export type TRecipientColor = keyof typeof RECIPIENT_COLOR_STYLES;
|
||||
|
||||
export const AVAILABLE_RECIPIENT_COLORS = [
|
||||
'green',
|
||||
'blue',
|
||||
'purple',
|
||||
'orange',
|
||||
'yellow',
|
||||
'pink',
|
||||
] satisfies TRecipientColor[];
|
||||
|
||||
export const useRecipientColors = (index: number) => {
|
||||
const key = AVAILABLE_RECIPIENT_COLORS[index % AVAILABLE_RECIPIENT_COLORS.length];
|
||||
|
||||
return RECIPIENT_COLOR_STYLES[key];
|
||||
comboBoxItem: '',
|
||||
}),
|
||||
green: once(() => generateStyles('green')),
|
||||
blue: once(() => generateStyles('blue')),
|
||||
purple: once(() => generateStyles('purple')),
|
||||
orange: once(() => generateStyles('orange')),
|
||||
yellow: once(() => generateStyles('yellow')),
|
||||
pink: once(() => generateStyles('pink')),
|
||||
};
|
||||
|
||||
export const getRecipientColorStyles = (index: number) => {
|
||||
// Disabling the rule since the hook doesn't do anything special and can
|
||||
// be used universally.
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
return useRecipientColors(index);
|
||||
const generateStyles = (recipientColor: TRecipientColor): RecipientColorStyles => {
|
||||
const { bg, border, ring, text } = CSS_PROPERTY;
|
||||
const { active, hover, groupHover, groupHoverFieldItem } = CSS_VARIANT;
|
||||
|
||||
const name = `recipient-${recipientColor}`;
|
||||
const value = getComputedStyle(document.documentElement).getPropertyValue(`--${name}`);
|
||||
const color = colord(`hsl(${value})`);
|
||||
|
||||
return {
|
||||
base: `${ring}-${name} ${hover}:${bg}-${name}/30`,
|
||||
baseRing: color.toRgbString(),
|
||||
baseRingHover: color.alpha(0.3).toRgbString(),
|
||||
baseTextHover: color.toRgbString(),
|
||||
fieldButton: `${hover}:${border}-${name} ${hover}:${bg}-${name}/30`,
|
||||
fieldButtonText: `${groupHover}:${text}-${name}`,
|
||||
fieldItem: 'group/field-item rounded-[2px]',
|
||||
fieldItemInitials: `${groupHoverFieldItem}:${bg}-${name}`,
|
||||
comboBoxTrigger: `ring-2 ${ring}-${name} ${hover}:${bg}-${name}/15 ${active}:${bg}-${name}/15 shadow-[0_0_0_5px_hsl(var(--${name})/10%),0_0_0_2px_hsl(var(--${name})/60%),0_0_0_0.5px_hsl(var(--${name}))]`,
|
||||
comboBoxItem: `${hover}:${bg}-${name}/15 ${active}:${bg}-${name}/15`,
|
||||
};
|
||||
};
|
||||
|
||||
const CSS_PROPERTY = {
|
||||
bg: 'bg',
|
||||
border: 'border',
|
||||
ring: 'ring',
|
||||
text: 'text',
|
||||
};
|
||||
|
||||
const CSS_VARIANT = {
|
||||
active: 'active',
|
||||
groupHover: 'group-hover',
|
||||
groupHoverFieldItem: 'group-hover/field-item',
|
||||
hover: 'hover',
|
||||
};
|
||||
|
||||
const AVAILABLE_RECIPIENT_COLORS = ['green', 'blue', 'purple', 'orange', 'yellow', 'pink'] as const;
|
||||
|
||||
export const RECIPIENT_DYNAMIC_CLASS = {
|
||||
pattern: new RegExp(
|
||||
`(${Object.values(CSS_PROPERTY).join('|')})-recipient-(${AVAILABLE_RECIPIENT_COLORS.join('|')})(\\/(15|30))?$`,
|
||||
),
|
||||
variants: Object.values(CSS_VARIANT),
|
||||
};
|
||||
|
||||
export const getRecipientColor = (index: number) => {
|
||||
return AVAILABLE_RECIPIENT_COLORS[Math.max(index, 0) % AVAILABLE_RECIPIENT_COLORS.length];
|
||||
};
|
||||
|
||||
export const getRecipientColorStyles = (colorOrIndex: TRecipientColor | number) => {
|
||||
const color = typeof colorOrIndex === 'number' ? getRecipientColor(colorOrIndex) : colorOrIndex;
|
||||
|
||||
return RECIPIENT_COLOR_STYLES[color]();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ import {
|
|||
} from '@documenso/lib/utils/recipients';
|
||||
|
||||
import { FieldToolTip } from '../../components/field/field-tooltip';
|
||||
import { useRecipientColors } from '../../lib/recipient-colors';
|
||||
import { getRecipientColorStyles } from '../../lib/recipient-colors';
|
||||
import { cn } from '../../lib/utils';
|
||||
import { Alert, AlertDescription } from '../alert';
|
||||
import { Card, CardContent } from '../card';
|
||||
|
|
@ -180,9 +180,7 @@ export const AddFieldsFormPartial = ({
|
|||
null,
|
||||
);
|
||||
const selectedSignerIndex = recipients.findIndex((r) => r.id === selectedSigner?.id);
|
||||
const selectedSignerStyles = useRecipientColors(
|
||||
selectedSignerIndex === -1 ? 0 : selectedSignerIndex,
|
||||
);
|
||||
const selectedSignerStyles = getRecipientColorStyles(selectedSignerIndex);
|
||||
|
||||
const [validateUninsertedFields, setValidateUninsertedFields] = useState(false);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
|
|||
import type { TFieldMetaSchema } from '@documenso/lib/types/field-meta';
|
||||
import { ZCheckboxFieldMeta, ZRadioFieldMeta } from '@documenso/lib/types/field-meta';
|
||||
|
||||
import { useRecipientColors } from '../../lib/recipient-colors';
|
||||
import { getRecipientColorStyles } from '../../lib/recipient-colors';
|
||||
import { cn } from '../../lib/utils';
|
||||
import { FieldContent } from './field-content';
|
||||
import type { TDocumentFlowFormSchema } from './types';
|
||||
|
|
@ -100,7 +100,7 @@ const FieldItemInner = ({
|
|||
`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${field.pageNumber}"]`,
|
||||
);
|
||||
|
||||
const signerStyles = useRecipientColors(recipientIndex);
|
||||
const signerStyles = getRecipientColorStyles(recipientIndex);
|
||||
|
||||
const isDevMode = searchParams.get('devmode') === 'true';
|
||||
|
||||
|
|
|
|||
|
|
@ -102,12 +102,8 @@ export const RecipientSelector = ({
|
|||
role="combobox"
|
||||
className={cn(
|
||||
'bg-background text-muted-foreground hover:text-foreground justify-between font-normal',
|
||||
getRecipientColorStyles(
|
||||
Math.max(
|
||||
recipients.findIndex((r) => r.id === selectedRecipient?.id),
|
||||
0,
|
||||
),
|
||||
).comboxBoxTrigger,
|
||||
getRecipientColorStyles(recipients.findIndex((r) => r.id === selectedRecipient?.id))
|
||||
.comboBoxTrigger,
|
||||
className,
|
||||
)}
|
||||
>
|
||||
|
|
@ -151,12 +147,8 @@ export const RecipientSelector = ({
|
|||
key={recipient.id}
|
||||
className={cn(
|
||||
'px-2 last:mb-1 [&:not(:first-child)]:mt-1',
|
||||
getRecipientColorStyles(
|
||||
Math.max(
|
||||
recipients.findIndex((r) => r.id === recipient.id),
|
||||
0,
|
||||
),
|
||||
).comboxBoxItem,
|
||||
getRecipientColorStyles(recipients.findIndex((r) => r.id === recipient.id))
|
||||
.comboBoxItem,
|
||||
{
|
||||
'text-muted-foreground': recipient.sendStatus === SendStatus.SENT,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ import { FRIENDLY_FIELD_TYPE } from '@documenso/ui/primitives/document-flow/type
|
|||
import { Popover, PopoverContent, PopoverTrigger } from '@documenso/ui/primitives/popover';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
import { getRecipientColorStyles, useRecipientColors } from '../../lib/recipient-colors';
|
||||
import { getRecipientColorStyles } from '../../lib/recipient-colors';
|
||||
import type { FieldFormType } from '../document-flow/add-fields';
|
||||
import { FieldAdvancedSettings } from '../document-flow/field-item-advanced-settings';
|
||||
import { Form } from '../form/form';
|
||||
|
|
@ -158,9 +158,7 @@ export const AddTemplateFieldsFormPartial = ({
|
|||
const [showRecipientsSelector, setShowRecipientsSelector] = useState(false);
|
||||
|
||||
const selectedSignerIndex = recipients.findIndex((r) => r.id === selectedSigner?.id);
|
||||
const selectedSignerStyles = useRecipientColors(
|
||||
selectedSignerIndex === -1 ? 0 : selectedSignerIndex,
|
||||
);
|
||||
const selectedSignerStyles = getRecipientColorStyles(selectedSignerIndex);
|
||||
|
||||
const onFieldCopy = useCallback(
|
||||
(event?: KeyboardEvent | null, options?: { duplicate?: boolean; duplicateAll?: boolean }) => {
|
||||
|
|
@ -653,7 +651,7 @@ export const AddTemplateFieldsFormPartial = ({
|
|||
role="combobox"
|
||||
className={cn(
|
||||
'mb-12 mt-2 justify-between bg-background font-normal text-muted-foreground hover:text-foreground',
|
||||
selectedSignerStyles?.comboxBoxTrigger,
|
||||
selectedSignerStyles?.comboBoxTrigger,
|
||||
)}
|
||||
>
|
||||
{selectedSigner?.email &&
|
||||
|
|
@ -710,11 +708,8 @@ export const AddTemplateFieldsFormPartial = ({
|
|||
className={cn(
|
||||
'px-2 last:mb-1 [&:not(:first-child)]:mt-1',
|
||||
getRecipientColorStyles(
|
||||
Math.max(
|
||||
recipients.findIndex((r) => r.id === recipient.id),
|
||||
0,
|
||||
),
|
||||
)?.comboxBoxItem,
|
||||
recipients.findIndex((r) => r.id === recipient.id),
|
||||
)?.comboBoxItem,
|
||||
)}
|
||||
onSelect={() => {
|
||||
setSelectedSigner(recipient);
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const baseConfig = require('@documenso/tailwind-config');
|
||||
const { RECIPIENT_DYNAMIC_CLASS } = require('./lib/recipient-colors');
|
||||
|
||||
module.exports = {
|
||||
...baseConfig,
|
||||
presets: [baseConfig],
|
||||
content: [
|
||||
...baseConfig.content,
|
||||
'./primitives/**/*.{ts,tsx}',
|
||||
'./components/**/*.{ts,tsx}',
|
||||
'./lib/**/*.{ts,tsx}',
|
||||
],
|
||||
safelist: [RECIPIENT_DYNAMIC_CLASS],
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue