mirror of
https://github.com/documenso/documenso.git
synced 2025-11-16 17:51:49 +10:00
feat: add horizontal radio
This commit is contained in:
@ -127,12 +127,12 @@ export const EnvelopeDistributeDialog = ({ envelope, trigger }: EnvelopeDistribu
|
|||||||
|
|
||||||
const distributionMethod = watch('meta.distributionMethod');
|
const distributionMethod = watch('meta.distributionMethod');
|
||||||
|
|
||||||
const everySignerHasSignature = useMemo(
|
const recipientsMissingSignatureFields = useMemo(
|
||||||
() =>
|
() =>
|
||||||
envelope.recipients
|
envelope.recipients.filter(
|
||||||
.filter((recipient) => recipient.role === RecipientRole.SIGNER)
|
(recipient) =>
|
||||||
.every((recipient) =>
|
recipient.role === RecipientRole.SIGNER &&
|
||||||
envelope.fields.some(
|
!envelope.fields.some(
|
||||||
(field) => field.type === FieldType.SIGNATURE && field.recipientId === recipient.id,
|
(field) => field.type === FieldType.SIGNATURE && field.recipientId === recipient.id,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -178,7 +178,7 @@ export const EnvelopeDistributeDialog = ({ envelope, trigger }: EnvelopeDistribu
|
|||||||
<Trans>Recipients will be able to sign the document once sent</Trans>
|
<Trans>Recipients will be able to sign the document once sent</Trans>
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
{everySignerHasSignature ? (
|
{recipientsMissingSignatureFields.length === 0 ? (
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={handleSubmit(onFormSubmit)}>
|
<form onSubmit={handleSubmit(onFormSubmit)}>
|
||||||
<fieldset disabled={isSubmitting}>
|
<fieldset disabled={isSubmitting}>
|
||||||
@ -350,6 +350,8 @@ export const EnvelopeDistributeDialog = ({ envelope, trigger }: EnvelopeDistribu
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<ul className="text-muted-foreground divide-y">
|
<ul className="text-muted-foreground divide-y">
|
||||||
|
{/* Todo: Envelopes - I don't think this section shows up */}
|
||||||
|
|
||||||
{recipients.length === 0 && (
|
{recipients.length === 0 && (
|
||||||
<li className="flex flex-col items-center justify-center py-6 text-sm">
|
<li className="flex flex-col items-center justify-center py-6 text-sm">
|
||||||
<Trans>No recipients</Trans>
|
<Trans>No recipients</Trans>
|
||||||
@ -427,10 +429,13 @@ export const EnvelopeDistributeDialog = ({ envelope, trigger }: EnvelopeDistribu
|
|||||||
<>
|
<>
|
||||||
<Alert variant="warning">
|
<Alert variant="warning">
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
<Trans>
|
<Trans>The following signers are missing signature fields:</Trans>
|
||||||
Some signers have not been assigned a signature field. Please assign at least 1
|
|
||||||
signature field to each signer before proceeding.
|
<ul className="ml-2 mt-1 list-inside list-disc">
|
||||||
</Trans>
|
{recipientsMissingSignatureFields.map((recipient) => (
|
||||||
|
<li key={recipient.id}>{recipient.email}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,32 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { Trans } from '@lingui/react/macro';
|
import { Trans, useLingui } from '@lingui/react/macro';
|
||||||
import { PlusIcon, Trash } from 'lucide-react';
|
import { PlusIcon, Trash } from 'lucide-react';
|
||||||
import { useForm, useWatch } from 'react-hook-form';
|
import { useForm, useWatch } from 'react-hook-form';
|
||||||
import { z } from 'zod';
|
import type { z } from 'zod';
|
||||||
|
|
||||||
import { type TRadioFieldMeta as RadioFieldMeta } from '@documenso/lib/types/field-meta';
|
import {
|
||||||
|
type TRadioFieldMeta as RadioFieldMeta,
|
||||||
|
ZRadioFieldMeta,
|
||||||
|
} from '@documenso/lib/types/field-meta';
|
||||||
import { Checkbox } from '@documenso/ui/primitives/checkbox';
|
import { Checkbox } from '@documenso/ui/primitives/checkbox';
|
||||||
import { Form, FormControl, FormField, FormItem } from '@documenso/ui/primitives/form/form';
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from '@documenso/ui/primitives/form/form';
|
||||||
import { Input } from '@documenso/ui/primitives/input';
|
import { Input } from '@documenso/ui/primitives/input';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from '@documenso/ui/primitives/select';
|
||||||
import { Separator } from '@documenso/ui/primitives/separator';
|
import { Separator } from '@documenso/ui/primitives/separator';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -17,18 +34,13 @@ import {
|
|||||||
EditorGenericRequiredField,
|
EditorGenericRequiredField,
|
||||||
} from './editor-field-generic-field-forms';
|
} from './editor-field-generic-field-forms';
|
||||||
|
|
||||||
const ZRadioFieldFormSchema = z
|
const ZRadioFieldFormSchema = ZRadioFieldMeta.pick({
|
||||||
.object({
|
label: true,
|
||||||
label: z.string().optional(),
|
direction: true,
|
||||||
values: z
|
values: true,
|
||||||
.object({ id: z.number(), checked: z.boolean(), value: z.string() })
|
required: true,
|
||||||
.array()
|
readOnly: true,
|
||||||
.min(1)
|
}).refine(
|
||||||
.optional(),
|
|
||||||
required: z.boolean().optional(),
|
|
||||||
readOnly: z.boolean().optional(),
|
|
||||||
})
|
|
||||||
.refine(
|
|
||||||
(data) => {
|
(data) => {
|
||||||
// There cannot be more than one checked option
|
// There cannot be more than one checked option
|
||||||
if (data.values) {
|
if (data.values) {
|
||||||
@ -53,9 +65,12 @@ export type EditorFieldRadioFormProps = {
|
|||||||
export const EditorFieldRadioForm = ({
|
export const EditorFieldRadioForm = ({
|
||||||
value = {
|
value = {
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
|
direction: 'vertical',
|
||||||
},
|
},
|
||||||
onValueChange,
|
onValueChange,
|
||||||
}: EditorFieldRadioFormProps) => {
|
}: EditorFieldRadioFormProps) => {
|
||||||
|
const { t } = useLingui();
|
||||||
|
|
||||||
const form = useForm<TRadioFieldFormSchema>({
|
const form = useForm<TRadioFieldFormSchema>({
|
||||||
resolver: zodResolver(ZRadioFieldFormSchema),
|
resolver: zodResolver(ZRadioFieldFormSchema),
|
||||||
mode: 'onChange',
|
mode: 'onChange',
|
||||||
@ -64,6 +79,7 @@ export const EditorFieldRadioForm = ({
|
|||||||
values: value.values || [{ id: 1, checked: false, value: 'Default value' }],
|
values: value.values || [{ id: 1, checked: false, value: 'Default value' }],
|
||||||
required: value.required || false,
|
required: value.required || false,
|
||||||
readOnly: value.readOnly || false,
|
readOnly: value.readOnly || false,
|
||||||
|
direction: value.direction || 'vertical',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -107,7 +123,35 @@ export const EditorFieldRadioForm = ({
|
|||||||
return (
|
return (
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form>
|
<form>
|
||||||
<fieldset className="flex flex-col gap-2 pb-2">
|
<fieldset className="flex flex-col gap-2">
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="direction"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
<Trans>Direction</Trans>
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Select value={field.value} onValueChange={field.onChange}>
|
||||||
|
<SelectTrigger className="text-muted-foreground bg-background w-full">
|
||||||
|
<SelectValue placeholder={t`Select direction`} />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent position="popper">
|
||||||
|
<SelectItem value="vertical">
|
||||||
|
<Trans>Vertical</Trans>
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="horizontal">
|
||||||
|
<Trans>Horizontal</Trans>
|
||||||
|
</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
<EditorGenericRequiredField formControl={form.control} />
|
<EditorGenericRequiredField formControl={form.control} />
|
||||||
|
|
||||||
<EditorGenericReadOnlyField formControl={form.control} />
|
<EditorGenericReadOnlyField formControl={form.control} />
|
||||||
|
|||||||
@ -96,7 +96,7 @@ export const EnvelopeEditorFieldDragDrop = ({
|
|||||||
selectedRecipientId,
|
selectedRecipientId,
|
||||||
selectedEnvelopeItemId,
|
selectedEnvelopeItemId,
|
||||||
}: EnvelopeEditorFieldDragDropProps) => {
|
}: EnvelopeEditorFieldDragDropProps) => {
|
||||||
const { envelope, editorFields, isTemplate } = useCurrentEnvelopeEditor();
|
const { envelope, editorFields, isTemplate, getRecipientColorKey } = useCurrentEnvelopeEditor();
|
||||||
|
|
||||||
const { t } = useLingui();
|
const { t } = useLingui();
|
||||||
|
|
||||||
@ -262,6 +262,10 @@ export const EnvelopeEditorFieldDragDrop = ({
|
|||||||
};
|
};
|
||||||
}, [onMouseClick, onMouseMove, selectedField]);
|
}, [onMouseClick, onMouseMove, selectedField]);
|
||||||
|
|
||||||
|
const selectedRecipientColor = useMemo(() => {
|
||||||
|
return selectedRecipientId ? getRecipientColorKey(selectedRecipientId) : 'green';
|
||||||
|
}, [selectedRecipientId, getRecipientColorKey]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="grid grid-cols-2 gap-x-2 gap-y-2.5">
|
<div className="grid grid-cols-2 gap-x-2 gap-y-2.5">
|
||||||
@ -273,12 +277,23 @@ export const EnvelopeEditorFieldDragDrop = ({
|
|||||||
onClick={() => setSelectedField(field.type)}
|
onClick={() => setSelectedField(field.type)}
|
||||||
onMouseDown={() => setSelectedField(field.type)}
|
onMouseDown={() => setSelectedField(field.type)}
|
||||||
data-selected={selectedField === field.type ? true : undefined}
|
data-selected={selectedField === field.type ? true : undefined}
|
||||||
className="group flex h-12 cursor-pointer items-center justify-center rounded-lg border border-gray-200 px-4 transition-colors hover:border-blue-300 hover:bg-blue-50"
|
className={cn(
|
||||||
|
'group flex h-12 cursor-pointer items-center justify-center rounded-lg border border-gray-200 px-4 transition-colors',
|
||||||
|
RECIPIENT_COLOR_STYLES[selectedRecipientColor].fieldButton,
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
className={cn(
|
className={cn(
|
||||||
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
|
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
|
||||||
field.className,
|
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',
|
||||||
|
},
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{field.type !== FieldType.SIGNATURE && <field.icon className="h-4 w-4" />}
|
{field.type !== FieldType.SIGNATURE && <field.icon className="h-4 w-4" />}
|
||||||
@ -292,8 +307,7 @@ export const EnvelopeEditorFieldDragDrop = ({
|
|||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'text-muted-foreground dark:text-muted-background pointer-events-none fixed z-50 flex cursor-pointer flex-col items-center justify-center rounded-[2px] bg-white ring-2 transition duration-200 [container-type:size]',
|
'text-muted-foreground dark:text-muted-background pointer-events-none fixed z-50 flex cursor-pointer flex-col items-center justify-center rounded-[2px] bg-white ring-2 transition duration-200 [container-type:size]',
|
||||||
// selectedSignerStyles?.base,
|
RECIPIENT_COLOR_STYLES[selectedRecipientColor].base,
|
||||||
RECIPIENT_COLOR_STYLES.yellow.base, // Todo: Envelopes
|
|
||||||
{
|
{
|
||||||
'-rotate-6 scale-90 opacity-50 dark:bg-black/20': !isFieldWithinBounds,
|
'-rotate-6 scale-90 opacity-50 dark:bg-black/20': !isFieldWithinBounds,
|
||||||
'dark:text-black/60': isFieldWithinBounds,
|
'dark:text-black/60': isFieldWithinBounds,
|
||||||
|
|||||||
@ -224,8 +224,12 @@ export const EnvelopeEditorPageUpload = () => {
|
|||||||
<div className="mx-auto max-w-4xl space-y-6 p-8">
|
<div className="mx-auto max-w-4xl space-y-6 p-8">
|
||||||
<Card backdropBlur={false} className="border">
|
<Card backdropBlur={false} className="border">
|
||||||
<CardHeader className="pb-3">
|
<CardHeader className="pb-3">
|
||||||
<CardTitle>Documents</CardTitle>
|
<CardTitle>
|
||||||
<CardDescription>Add and configure multiple documents</CardDescription>
|
<Trans>Documents</Trans>
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
<Trans>Add and configure multiple documents</Trans>
|
||||||
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardContent>
|
<CardContent>
|
||||||
|
|||||||
@ -128,6 +128,18 @@ export default function EnvelopeEditor() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Watch the URL params and setStep if the step changes.
|
||||||
|
useEffect(() => {
|
||||||
|
const stepParam = searchParams.get('step') || envelopeEditorSteps[0].id;
|
||||||
|
|
||||||
|
const foundStep = envelopeEditorSteps.find((step) => step.id === stepParam);
|
||||||
|
|
||||||
|
if (foundStep && foundStep.id !== currentStep) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||||
|
navigateToStep(foundStep.id as EnvelopeEditorStep);
|
||||||
|
}
|
||||||
|
}, [searchParams]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isAutosaving) {
|
if (!isAutosaving) {
|
||||||
setIsStepLoading(false);
|
setIsStepLoading(false);
|
||||||
@ -340,7 +352,6 @@ export default function EnvelopeEditor() {
|
|||||||
|
|
||||||
{/* Main Content - Changes based on current step */}
|
{/* Main Content - Changes based on current step */}
|
||||||
<div className="flex-1 overflow-y-auto">
|
<div className="flex-1 overflow-y-auto">
|
||||||
<p>{isAutosaving ? 'Autosaving...' : 'Not autosaving'}</p>
|
|
||||||
<AnimateGenericFadeInOut key={currentStep}>
|
<AnimateGenericFadeInOut key={currentStep}>
|
||||||
{match({ currentStep, isStepLoading })
|
{match({ currentStep, isStepLoading })
|
||||||
.with({ isStepLoading: true }, () => <SpinnerBox className="py-32" />)
|
.with({ isStepLoading: true }, () => <SpinnerBox className="py-32" />)
|
||||||
|
|||||||
@ -135,7 +135,12 @@ export const EnvelopeEditorProvider = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const envelopeRecipientSetMutationQuery = trpc.envelope.recipient.set.useMutation({
|
const envelopeRecipientSetMutationQuery = trpc.envelope.recipient.set.useMutation({
|
||||||
onSuccess: () => {
|
onSuccess: ({ recipients }) => {
|
||||||
|
setEnvelope((prev) => ({
|
||||||
|
...prev,
|
||||||
|
recipients,
|
||||||
|
}));
|
||||||
|
|
||||||
setAutosaveError(false);
|
setAutosaveError(false);
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
@ -215,14 +220,15 @@ export const EnvelopeEditorProvider = ({
|
|||||||
|
|
||||||
const getRecipientColorKey = useCallback(
|
const getRecipientColorKey = useCallback(
|
||||||
(recipientId: number) => {
|
(recipientId: number) => {
|
||||||
// Todo: Envelopes - Local recipients
|
|
||||||
const recipientIndex = envelope.recipients.findIndex(
|
const recipientIndex = envelope.recipients.findIndex(
|
||||||
(recipient) => recipient.id === recipientId,
|
(recipient) => recipient.id === recipientId,
|
||||||
);
|
);
|
||||||
|
|
||||||
return AVAILABLE_RECIPIENT_COLORS[Math.max(recipientIndex, 0)];
|
return AVAILABLE_RECIPIENT_COLORS[
|
||||||
|
Math.max(recipientIndex, 0) % AVAILABLE_RECIPIENT_COLORS.length
|
||||||
|
];
|
||||||
},
|
},
|
||||||
[envelope.recipients], // Todo: Envelopes - Local recipients
|
[envelope.recipients],
|
||||||
);
|
);
|
||||||
|
|
||||||
const { refetch: reloadEnvelope, isLoading: isReloadingEnvelope } = trpc.envelope.get.useQuery(
|
const { refetch: reloadEnvelope, isLoading: isReloadingEnvelope } = trpc.envelope.get.useQuery(
|
||||||
|
|||||||
@ -81,6 +81,7 @@ export const ZRadioFieldMeta = ZBaseFieldMeta.extend({
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.optional(),
|
.optional(),
|
||||||
|
direction: z.enum(['vertical', 'horizontal']).optional().default('vertical'),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TRadioFieldMeta = z.infer<typeof ZRadioFieldMeta>;
|
export type TRadioFieldMeta = z.infer<typeof ZRadioFieldMeta>;
|
||||||
@ -278,6 +279,7 @@ export const FIELD_RADIO_META_DEFAULT_VALUES: TRadioFieldMeta = {
|
|||||||
values: [{ id: 1, checked: false, value: '' }],
|
values: [{ id: 1, checked: false, value: '' }],
|
||||||
required: false,
|
required: false,
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
|
direction: 'vertical',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FIELD_CHECKBOX_META_DEFAULT_VALUES: TCheckboxFieldMeta = {
|
export const FIELD_CHECKBOX_META_DEFAULT_VALUES: TCheckboxFieldMeta = {
|
||||||
|
|||||||
@ -107,6 +107,11 @@ type CalculateMultiItemPositionOptions = {
|
|||||||
*/
|
*/
|
||||||
fieldPadding: number;
|
fieldPadding: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The direction of the items.
|
||||||
|
*/
|
||||||
|
direction: 'horizontal' | 'vertical';
|
||||||
|
|
||||||
type: 'checkbox' | 'radio';
|
type: 'checkbox' | 'radio';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,6 +127,7 @@ export const calculateMultiItemPosition = (options: CalculateMultiItemPositionOp
|
|||||||
itemSize,
|
itemSize,
|
||||||
spacingBetweenItemAndText,
|
spacingBetweenItemAndText,
|
||||||
fieldPadding,
|
fieldPadding,
|
||||||
|
direction,
|
||||||
type,
|
type,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
@ -130,6 +136,39 @@ export const calculateMultiItemPosition = (options: CalculateMultiItemPositionOp
|
|||||||
const innerFieldX = fieldPadding;
|
const innerFieldX = fieldPadding;
|
||||||
const innerFieldY = fieldPadding;
|
const innerFieldY = fieldPadding;
|
||||||
|
|
||||||
|
if (direction === 'horizontal') {
|
||||||
|
const itemHeight = innerFieldHeight;
|
||||||
|
const itemWidth = innerFieldWidth / itemCount;
|
||||||
|
|
||||||
|
const y = innerFieldY;
|
||||||
|
const x = itemIndex * itemWidth + innerFieldX;
|
||||||
|
|
||||||
|
let itemInputY = y + itemHeight / 2 - itemSize / 2;
|
||||||
|
let itemInputX = x;
|
||||||
|
|
||||||
|
// We need a little different logic to center the radio circle icon.
|
||||||
|
if (type === 'radio') {
|
||||||
|
itemInputX = x + itemSize / 2;
|
||||||
|
itemInputY = y + itemHeight / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const textX = x + itemSize + spacingBetweenItemAndText;
|
||||||
|
const textY = y;
|
||||||
|
|
||||||
|
// Multiplied by 2 for extra padding on the right hand side of the text and the next item.
|
||||||
|
const textWidth = itemWidth - itemSize - spacingBetweenItemAndText * 2;
|
||||||
|
const textHeight = itemHeight;
|
||||||
|
|
||||||
|
return {
|
||||||
|
itemInputX,
|
||||||
|
itemInputY,
|
||||||
|
textX,
|
||||||
|
textY,
|
||||||
|
textWidth,
|
||||||
|
textHeight,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const itemHeight = innerFieldHeight / itemCount;
|
const itemHeight = innerFieldHeight / itemCount;
|
||||||
|
|
||||||
const y = itemIndex * itemHeight + innerFieldY;
|
const y = itemIndex * itemHeight + innerFieldY;
|
||||||
@ -137,6 +176,7 @@ export const calculateMultiItemPosition = (options: CalculateMultiItemPositionOp
|
|||||||
let itemInputY = y + itemHeight / 2 - itemSize / 2;
|
let itemInputY = y + itemHeight / 2 - itemSize / 2;
|
||||||
let itemInputX = innerFieldX;
|
let itemInputX = innerFieldX;
|
||||||
|
|
||||||
|
// We need a little different logic to center the radio circle icon.
|
||||||
if (type === 'radio') {
|
if (type === 'radio') {
|
||||||
itemInputX = innerFieldX + itemSize / 2;
|
itemInputX = innerFieldX + itemSize / 2;
|
||||||
itemInputY = y + itemHeight / 2;
|
itemInputY = y + itemHeight / 2;
|
||||||
|
|||||||
@ -26,6 +26,9 @@ export const renderCheckboxFieldElement = (
|
|||||||
|
|
||||||
fieldGroup.add(upsertFieldRect(field, options));
|
fieldGroup.add(upsertFieldRect(field, options));
|
||||||
|
|
||||||
|
const checkboxMeta: TCheckboxFieldMeta | null = (field.fieldMeta as TCheckboxFieldMeta) || null;
|
||||||
|
const checkboxValues = checkboxMeta?.values || [];
|
||||||
|
|
||||||
if (isFirstRender) {
|
if (isFirstRender) {
|
||||||
pageLayer.add(fieldGroup);
|
pageLayer.add(fieldGroup);
|
||||||
|
|
||||||
@ -72,6 +75,7 @@ export const renderCheckboxFieldElement = (
|
|||||||
itemSize: checkboxSize,
|
itemSize: checkboxSize,
|
||||||
spacingBetweenItemAndText: spacingBetweenCheckboxAndText,
|
spacingBetweenItemAndText: spacingBetweenCheckboxAndText,
|
||||||
fieldPadding: checkboxFieldPadding,
|
fieldPadding: checkboxFieldPadding,
|
||||||
|
direction: checkboxMeta?.direction || 'vertical',
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -113,9 +117,6 @@ export const renderCheckboxFieldElement = (
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkboxMeta: TCheckboxFieldMeta | null = (field.fieldMeta as TCheckboxFieldMeta) || null;
|
|
||||||
const checkboxValues = checkboxMeta?.values || [];
|
|
||||||
|
|
||||||
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
|
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
|
||||||
|
|
||||||
checkboxValues.forEach(({ id, value, checked }, index) => {
|
checkboxValues.forEach(({ id, value, checked }, index) => {
|
||||||
@ -128,6 +129,7 @@ export const renderCheckboxFieldElement = (
|
|||||||
itemSize: checkboxSize,
|
itemSize: checkboxSize,
|
||||||
spacingBetweenItemAndText: spacingBetweenCheckboxAndText,
|
spacingBetweenItemAndText: spacingBetweenCheckboxAndText,
|
||||||
fieldPadding: checkboxFieldPadding,
|
fieldPadding: checkboxFieldPadding,
|
||||||
|
direction: checkboxMeta?.direction || 'vertical',
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,9 @@ export const renderRadioFieldElement = (
|
|||||||
|
|
||||||
fieldGroup.add(upsertFieldRect(field, options));
|
fieldGroup.add(upsertFieldRect(field, options));
|
||||||
|
|
||||||
|
const radioMeta: TRadioFieldMeta | null = (field.fieldMeta as TRadioFieldMeta) || null;
|
||||||
|
const radioValues = radioMeta?.values || [];
|
||||||
|
|
||||||
if (isFirstRender) {
|
if (isFirstRender) {
|
||||||
pageLayer.add(fieldGroup);
|
pageLayer.add(fieldGroup);
|
||||||
|
|
||||||
@ -66,6 +69,7 @@ export const renderRadioFieldElement = (
|
|||||||
spacingBetweenItemAndText: spacingBetweenRadioAndText,
|
spacingBetweenItemAndText: spacingBetweenRadioAndText,
|
||||||
fieldPadding: radioFieldPadding,
|
fieldPadding: radioFieldPadding,
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
|
direction: radioMeta?.direction || 'vertical',
|
||||||
});
|
});
|
||||||
|
|
||||||
circleElement.setAttrs({
|
circleElement.setAttrs({
|
||||||
@ -104,9 +108,6 @@ export const renderRadioFieldElement = (
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const radioMeta: TRadioFieldMeta | null = (field.fieldMeta as TRadioFieldMeta) || null;
|
|
||||||
const radioValues = radioMeta?.values || [];
|
|
||||||
|
|
||||||
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
|
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
|
||||||
|
|
||||||
radioValues.forEach(({ value, checked }, index) => {
|
radioValues.forEach(({ value, checked }, index) => {
|
||||||
@ -120,6 +121,7 @@ export const renderRadioFieldElement = (
|
|||||||
spacingBetweenItemAndText: spacingBetweenRadioAndText,
|
spacingBetweenItemAndText: spacingBetweenRadioAndText,
|
||||||
fieldPadding: radioFieldPadding,
|
fieldPadding: radioFieldPadding,
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
|
direction: radioMeta?.direction || 'vertical',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Circle which represents the radio button.
|
// Circle which represents the radio button.
|
||||||
|
|||||||
@ -9,6 +9,7 @@ export type RecipientColorStyles = {
|
|||||||
base: string;
|
base: string;
|
||||||
baseRing: string;
|
baseRing: string;
|
||||||
baseRingHover: string;
|
baseRingHover: string;
|
||||||
|
fieldButton: string;
|
||||||
fieldItem: string;
|
fieldItem: string;
|
||||||
fieldItemInitials: string;
|
fieldItemInitials: string;
|
||||||
comboxBoxTrigger: string;
|
comboxBoxTrigger: string;
|
||||||
@ -23,6 +24,7 @@ export const RECIPIENT_COLOR_STYLES = {
|
|||||||
base: 'ring-neutral-400',
|
base: 'ring-neutral-400',
|
||||||
baseRing: 'rgba(176, 176, 176, 1)',
|
baseRing: 'rgba(176, 176, 176, 1)',
|
||||||
baseRingHover: 'rgba(176, 176, 176, 1)',
|
baseRingHover: 'rgba(176, 176, 176, 1)',
|
||||||
|
fieldButton: 'border-neutral-400 hover:border-neutral-400',
|
||||||
fieldItem: 'group/field-item rounded-[2px]',
|
fieldItem: 'group/field-item rounded-[2px]',
|
||||||
fieldItemInitials: '',
|
fieldItemInitials: '',
|
||||||
comboxBoxTrigger:
|
comboxBoxTrigger:
|
||||||
@ -34,6 +36,7 @@ export const RECIPIENT_COLOR_STYLES = {
|
|||||||
base: 'ring-recipient-green hover:bg-recipient-green/30',
|
base: 'ring-recipient-green hover:bg-recipient-green/30',
|
||||||
baseRing: 'rgba(122, 195, 85, 1)',
|
baseRing: 'rgba(122, 195, 85, 1)',
|
||||||
baseRingHover: 'rgba(122, 195, 85, 0.3)',
|
baseRingHover: 'rgba(122, 195, 85, 0.3)',
|
||||||
|
fieldButton: 'hover:border-recipient-green hover:bg-recipient-green/30 ',
|
||||||
fieldItem: 'group/field-item rounded-[2px]',
|
fieldItem: 'group/field-item rounded-[2px]',
|
||||||
fieldItemInitials: 'group-hover/field-item:bg-recipient-green',
|
fieldItemInitials: 'group-hover/field-item:bg-recipient-green',
|
||||||
comboxBoxTrigger:
|
comboxBoxTrigger:
|
||||||
@ -45,6 +48,7 @@ export const RECIPIENT_COLOR_STYLES = {
|
|||||||
base: 'ring-recipient-blue hover:bg-recipient-blue/30',
|
base: 'ring-recipient-blue hover:bg-recipient-blue/30',
|
||||||
baseRing: 'rgba(56, 123, 199, 1)',
|
baseRing: 'rgba(56, 123, 199, 1)',
|
||||||
baseRingHover: 'rgba(56, 123, 199, 0.3)',
|
baseRingHover: 'rgba(56, 123, 199, 0.3)',
|
||||||
|
fieldButton: 'hover:border-recipient-blue hover:bg-recipient-blue/30',
|
||||||
fieldItem: 'group/field-item rounded-[2px]',
|
fieldItem: 'group/field-item rounded-[2px]',
|
||||||
fieldItemInitials: 'group-hover/field-item:bg-recipient-blue',
|
fieldItemInitials: 'group-hover/field-item:bg-recipient-blue',
|
||||||
comboxBoxTrigger:
|
comboxBoxTrigger:
|
||||||
@ -56,6 +60,7 @@ export const RECIPIENT_COLOR_STYLES = {
|
|||||||
base: 'ring-recipient-purple hover:bg-recipient-purple/30',
|
base: 'ring-recipient-purple hover:bg-recipient-purple/30',
|
||||||
baseRing: 'rgba(151, 71, 255, 1)',
|
baseRing: 'rgba(151, 71, 255, 1)',
|
||||||
baseRingHover: 'rgba(151, 71, 255, 0.3)',
|
baseRingHover: 'rgba(151, 71, 255, 0.3)',
|
||||||
|
fieldButton: 'hover:border-recipient-purple hover:bg-recipient-purple/30',
|
||||||
fieldItem: 'group/field-item rounded-[2px]',
|
fieldItem: 'group/field-item rounded-[2px]',
|
||||||
fieldItemInitials: 'group-hover/field-item:bg-recipient-purple',
|
fieldItemInitials: 'group-hover/field-item:bg-recipient-purple',
|
||||||
comboxBoxTrigger:
|
comboxBoxTrigger:
|
||||||
@ -67,6 +72,7 @@ export const RECIPIENT_COLOR_STYLES = {
|
|||||||
base: 'ring-recipient-orange hover:bg-recipient-orange/30',
|
base: 'ring-recipient-orange hover:bg-recipient-orange/30',
|
||||||
baseRing: 'rgba(246, 159, 30, 1)',
|
baseRing: 'rgba(246, 159, 30, 1)',
|
||||||
baseRingHover: 'rgba(246, 159, 30, 0.3)',
|
baseRingHover: 'rgba(246, 159, 30, 0.3)',
|
||||||
|
fieldButton: 'hover:border-recipient-orange hover:bg-recipient-orange/30',
|
||||||
fieldItem: 'group/field-item rounded-[2px]',
|
fieldItem: 'group/field-item rounded-[2px]',
|
||||||
fieldItemInitials: 'group-hover/field-item:bg-recipient-orange',
|
fieldItemInitials: 'group-hover/field-item:bg-recipient-orange',
|
||||||
comboxBoxTrigger:
|
comboxBoxTrigger:
|
||||||
@ -78,6 +84,7 @@ export const RECIPIENT_COLOR_STYLES = {
|
|||||||
base: 'ring-recipient-yellow hover:bg-recipient-yellow/30',
|
base: 'ring-recipient-yellow hover:bg-recipient-yellow/30',
|
||||||
baseRing: 'rgba(219, 186, 0, 1)',
|
baseRing: 'rgba(219, 186, 0, 1)',
|
||||||
baseRingHover: 'rgba(219, 186, 0, 0.3)',
|
baseRingHover: 'rgba(219, 186, 0, 0.3)',
|
||||||
|
fieldButton: 'hover:border-recipient-yellow hover:bg-recipient-yellow/30',
|
||||||
fieldItem: 'group/field-item rounded-[2px]',
|
fieldItem: 'group/field-item rounded-[2px]',
|
||||||
fieldItemInitials: 'group-hover/field-item:bg-recipient-yellow',
|
fieldItemInitials: 'group-hover/field-item:bg-recipient-yellow',
|
||||||
comboxBoxTrigger:
|
comboxBoxTrigger:
|
||||||
@ -89,6 +96,7 @@ export const RECIPIENT_COLOR_STYLES = {
|
|||||||
base: 'ring-recipient-pink hover:bg-recipient-pink/30',
|
base: 'ring-recipient-pink hover:bg-recipient-pink/30',
|
||||||
baseRing: 'rgba(217, 74, 186, 1)',
|
baseRing: 'rgba(217, 74, 186, 1)',
|
||||||
baseRingHover: 'rgba(217, 74, 186, 0.3)',
|
baseRingHover: 'rgba(217, 74, 186, 0.3)',
|
||||||
|
fieldButton: 'hover:border-recipient-pink hover:bg-recipient-pink/30',
|
||||||
fieldItem: 'group/field-item rounded-[2px]',
|
fieldItem: 'group/field-item rounded-[2px]',
|
||||||
fieldItemInitials: 'group-hover/field-item:bg-recipient-pink',
|
fieldItemInitials: 'group-hover/field-item:bg-recipient-pink',
|
||||||
comboxBoxTrigger:
|
comboxBoxTrigger:
|
||||||
|
|||||||
Reference in New Issue
Block a user