mirror of
https://github.com/documenso/documenso.git
synced 2025-11-13 16:23:06 +10:00
fix: envelope styling (#2102)
This commit is contained in:
@ -129,3 +129,58 @@ export const createSpinner = ({
|
||||
|
||||
return loadingGroup;
|
||||
};
|
||||
|
||||
type CreateFieldHoverInteractionOptions = {
|
||||
options: RenderFieldElementOptions;
|
||||
fieldGroup: Konva.Group;
|
||||
fieldRect: Konva.Rect;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds smooth transition-like behavior for hover effects to the field group and rectangle.
|
||||
*/
|
||||
export const createFieldHoverInteraction = ({
|
||||
options,
|
||||
fieldGroup,
|
||||
fieldRect,
|
||||
}: CreateFieldHoverInteractionOptions) => {
|
||||
const { mode } = options;
|
||||
|
||||
if (mode === 'export' || !options.color) {
|
||||
return;
|
||||
}
|
||||
|
||||
const hoverColor = RECIPIENT_COLOR_STYLES[options.color].baseRingHover;
|
||||
|
||||
fieldGroup.on('mouseover', () => {
|
||||
new Konva.Tween({
|
||||
node: fieldRect,
|
||||
duration: 0.3,
|
||||
fill: hoverColor,
|
||||
}).play();
|
||||
});
|
||||
|
||||
fieldGroup.on('mouseout', () => {
|
||||
new Konva.Tween({
|
||||
node: fieldRect,
|
||||
duration: 0.3,
|
||||
fill: DEFAULT_RECT_BACKGROUND,
|
||||
}).play();
|
||||
});
|
||||
|
||||
fieldGroup.on('transformstart', () => {
|
||||
new Konva.Tween({
|
||||
node: fieldRect,
|
||||
duration: 0.3,
|
||||
fill: hoverColor,
|
||||
}).play();
|
||||
});
|
||||
|
||||
fieldGroup.on('transformend', () => {
|
||||
new Konva.Tween({
|
||||
node: fieldRect,
|
||||
duration: 0.3,
|
||||
fill: DEFAULT_RECT_BACKGROUND,
|
||||
}).play();
|
||||
});
|
||||
};
|
||||
|
||||
@ -4,6 +4,7 @@ import { match } from 'ts-pattern';
|
||||
import { DEFAULT_STANDARD_FONT_SIZE } from '../../constants/pdf';
|
||||
import type { TCheckboxFieldMeta } from '../../types/field-meta';
|
||||
import {
|
||||
createFieldHoverInteraction,
|
||||
konvaTextFill,
|
||||
konvaTextFontFamily,
|
||||
upsertFieldGroup,
|
||||
@ -26,25 +27,27 @@ export const renderCheckboxFieldElement = (
|
||||
) => {
|
||||
const { pageWidth, pageHeight, pageLayer, mode } = options;
|
||||
|
||||
const isFirstRender = !pageLayer.findOne(`#${field.renderId}`);
|
||||
|
||||
const fieldGroup = upsertFieldGroup(field, options);
|
||||
|
||||
// Clear previous children and listeners to re-render fresh.
|
||||
fieldGroup.removeChildren();
|
||||
fieldGroup.off('transform');
|
||||
|
||||
fieldGroup.add(upsertFieldRect(field, options));
|
||||
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
|
||||
|
||||
const checkboxMeta: TCheckboxFieldMeta | null = (field.fieldMeta as TCheckboxFieldMeta) || null;
|
||||
const checkboxValues = checkboxMeta?.values || [];
|
||||
|
||||
const fontSize = checkboxMeta?.fontSize || DEFAULT_STANDARD_FONT_SIZE;
|
||||
const isFirstRender = !pageLayer.findOne(`#${field.renderId}`);
|
||||
|
||||
// Clear previous children and listeners to re-render fresh.
|
||||
const fieldGroup = upsertFieldGroup(field, options);
|
||||
fieldGroup.removeChildren();
|
||||
fieldGroup.off('transform');
|
||||
|
||||
if (isFirstRender) {
|
||||
pageLayer.add(fieldGroup);
|
||||
}
|
||||
|
||||
const fieldRect = upsertFieldRect(field, options);
|
||||
fieldGroup.add(fieldRect);
|
||||
|
||||
const fontSize = checkboxMeta?.fontSize || DEFAULT_STANDARD_FONT_SIZE;
|
||||
|
||||
// Handle rescaling items during transforms.
|
||||
fieldGroup.on('transform', () => {
|
||||
const groupScaleX = fieldGroup.scaleX();
|
||||
@ -127,11 +130,9 @@ export const renderCheckboxFieldElement = (
|
||||
pageLayer.batchDraw();
|
||||
});
|
||||
|
||||
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
|
||||
|
||||
const checkedValues: number[] = field.customText ? JSON.parse(field.customText) : [];
|
||||
|
||||
checkboxValues.forEach(({ id, value, checked }, index) => {
|
||||
checkboxValues.forEach(({ value, checked }, index) => {
|
||||
const isCheckboxChecked = match(mode)
|
||||
.with('edit', () => checked)
|
||||
.with('sign', () => checkedValues.includes(index))
|
||||
@ -145,8 +146,6 @@ export const renderCheckboxFieldElement = (
|
||||
})
|
||||
.exhaustive();
|
||||
|
||||
console.log('wtf?');
|
||||
|
||||
const itemSize = calculateCheckboxSize(fontSize);
|
||||
|
||||
const { itemInputX, itemInputY, textX, textY, textWidth, textHeight } =
|
||||
@ -211,6 +210,8 @@ export const renderCheckboxFieldElement = (
|
||||
fieldGroup.add(text);
|
||||
});
|
||||
|
||||
createFieldHoverInteraction({ fieldGroup, fieldRect, options });
|
||||
|
||||
return {
|
||||
fieldGroup,
|
||||
isFirstRender,
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { FieldType } from '@prisma/client';
|
||||
import Konva from 'konva';
|
||||
|
||||
import { DEFAULT_STANDARD_FONT_SIZE } from '../../constants/pdf';
|
||||
import type { TDropdownFieldMeta } from '../../types/field-meta';
|
||||
import {
|
||||
createFieldHoverInteraction,
|
||||
konvaTextFill,
|
||||
konvaTextFontFamily,
|
||||
upsertFieldGroup,
|
||||
@ -48,79 +50,30 @@ export const renderDropdownFieldElement = (
|
||||
field: FieldToRender,
|
||||
options: RenderFieldElementOptions,
|
||||
) => {
|
||||
const { pageWidth, pageHeight, pageLayer, mode } = options;
|
||||
const { pageWidth, pageHeight, pageLayer, mode, translations } = options;
|
||||
|
||||
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
|
||||
|
||||
const dropdownMeta: TDropdownFieldMeta | null = (field.fieldMeta as TDropdownFieldMeta) || null;
|
||||
|
||||
let selectedValue = translations?.[FieldType.DROPDOWN] || 'Select Option';
|
||||
|
||||
const isFirstRender = !pageLayer.findOne(`#${field.renderId}`);
|
||||
|
||||
const fieldGroup = upsertFieldGroup(field, options);
|
||||
|
||||
// Clear previous children to re-render fresh.
|
||||
const fieldGroup = upsertFieldGroup(field, options);
|
||||
fieldGroup.removeChildren();
|
||||
fieldGroup.off('transform');
|
||||
|
||||
fieldGroup.add(upsertFieldRect(field, options));
|
||||
const fieldRect = upsertFieldRect(field, options);
|
||||
fieldGroup.add(fieldRect);
|
||||
|
||||
if (isFirstRender) {
|
||||
pageLayer.add(fieldGroup);
|
||||
|
||||
fieldGroup.on('transform', () => {
|
||||
const groupScaleX = fieldGroup.scaleX();
|
||||
const groupScaleY = fieldGroup.scaleY();
|
||||
|
||||
const fieldRect = fieldGroup.findOne('.field-rect');
|
||||
const text = fieldGroup.findOne('.dropdown-selected-text');
|
||||
const arrow = fieldGroup.findOne('.dropdown-arrow');
|
||||
|
||||
if (!fieldRect || !text || !arrow) {
|
||||
console.log('fieldRect or text or arrow not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const rectWidth = fieldRect.width() * groupScaleX;
|
||||
const rectHeight = fieldRect.height() * groupScaleY;
|
||||
|
||||
const { arrowX, arrowY, textX, textY, textWidth, textHeight } = calculateDropdownPosition({
|
||||
fieldWidth: rectWidth,
|
||||
fieldHeight: rectHeight,
|
||||
});
|
||||
|
||||
arrow.setAttrs({
|
||||
x: arrowX,
|
||||
y: arrowY,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
});
|
||||
|
||||
text.setAttrs({
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
x: textX,
|
||||
y: textY,
|
||||
width: textWidth,
|
||||
height: textHeight,
|
||||
});
|
||||
|
||||
fieldRect.setAttrs({
|
||||
width: rectWidth,
|
||||
height: rectHeight,
|
||||
});
|
||||
|
||||
fieldGroup.scale({
|
||||
x: 1,
|
||||
y: 1,
|
||||
});
|
||||
|
||||
pageLayer.batchDraw();
|
||||
});
|
||||
}
|
||||
|
||||
const dropdownMeta: TDropdownFieldMeta | null = (field.fieldMeta as TDropdownFieldMeta) || null;
|
||||
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
|
||||
|
||||
const fontSize = dropdownMeta?.fontSize || DEFAULT_STANDARD_FONT_SIZE;
|
||||
|
||||
// Todo: Envelopes - Translations
|
||||
let selectedValue = 'Select Option';
|
||||
|
||||
if (field.inserted) {
|
||||
selectedValue = field.customText;
|
||||
}
|
||||
@ -158,27 +111,63 @@ export const renderDropdownFieldElement = (
|
||||
visible: mode !== 'export',
|
||||
});
|
||||
|
||||
// Add hover state for dropdown
|
||||
fieldGroup.on('mouseenter', () => {
|
||||
// dropdownContainer.stroke('#2563EB');
|
||||
// dropdownContainer.strokeWidth(2);
|
||||
document.body.style.cursor = 'pointer';
|
||||
pageLayer.batchDraw();
|
||||
});
|
||||
|
||||
fieldGroup.on('mouseleave', () => {
|
||||
// dropdownContainer.stroke('#374151');
|
||||
// dropdownContainer.strokeWidth(2);
|
||||
document.body.style.cursor = 'default';
|
||||
pageLayer.batchDraw();
|
||||
});
|
||||
|
||||
fieldGroup.add(selectedText);
|
||||
|
||||
if (!field.inserted || mode === 'export') {
|
||||
fieldGroup.add(arrow);
|
||||
}
|
||||
|
||||
fieldGroup.on('transform', () => {
|
||||
const groupScaleX = fieldGroup.scaleX();
|
||||
const groupScaleY = fieldGroup.scaleY();
|
||||
|
||||
const fieldRect = fieldGroup.findOne('.field-rect');
|
||||
const text = fieldGroup.findOne('.dropdown-selected-text');
|
||||
const arrow = fieldGroup.findOne('.dropdown-arrow');
|
||||
|
||||
if (!fieldRect || !text || !arrow) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rectWidth = fieldRect.width() * groupScaleX;
|
||||
const rectHeight = fieldRect.height() * groupScaleY;
|
||||
|
||||
const { arrowX, arrowY, textX, textY, textWidth, textHeight } = calculateDropdownPosition({
|
||||
fieldWidth: rectWidth,
|
||||
fieldHeight: rectHeight,
|
||||
});
|
||||
|
||||
arrow.setAttrs({
|
||||
x: arrowX,
|
||||
y: arrowY,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
});
|
||||
|
||||
text.setAttrs({
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
x: textX,
|
||||
y: textY,
|
||||
width: textWidth,
|
||||
height: textHeight,
|
||||
});
|
||||
|
||||
fieldRect.setAttrs({
|
||||
width: rectWidth,
|
||||
height: rectHeight,
|
||||
});
|
||||
|
||||
fieldGroup.scale({
|
||||
x: 1,
|
||||
y: 1,
|
||||
});
|
||||
|
||||
pageLayer.batchDraw();
|
||||
});
|
||||
|
||||
createFieldHoverInteraction({ fieldGroup, fieldRect, options });
|
||||
|
||||
return {
|
||||
fieldGroup,
|
||||
isFirstRender,
|
||||
|
||||
@ -4,6 +4,7 @@ import { match } from 'ts-pattern';
|
||||
import { DEFAULT_STANDARD_FONT_SIZE } from '../../constants/pdf';
|
||||
import type { TRadioFieldMeta } from '../../types/field-meta';
|
||||
import {
|
||||
createFieldHoverInteraction,
|
||||
konvaTextFill,
|
||||
konvaTextFontFamily,
|
||||
upsertFieldGroup,
|
||||
@ -26,25 +27,24 @@ export const renderRadioFieldElement = (
|
||||
) => {
|
||||
const { pageWidth, pageHeight, pageLayer, mode } = options;
|
||||
|
||||
const isFirstRender = !pageLayer.findOne(`#${field.renderId}`);
|
||||
|
||||
const fieldGroup = upsertFieldGroup(field, options);
|
||||
|
||||
// Clear previous children to re-render fresh
|
||||
fieldGroup.removeChildren();
|
||||
|
||||
fieldGroup.add(upsertFieldRect(field, options));
|
||||
|
||||
const radioMeta: TRadioFieldMeta | null = (field.fieldMeta as TRadioFieldMeta) || null;
|
||||
const radioValues = radioMeta?.values || [];
|
||||
|
||||
const fontSize = radioMeta?.fontSize || DEFAULT_STANDARD_FONT_SIZE;
|
||||
const isFirstRender = !pageLayer.findOne(`#${field.renderId}`);
|
||||
|
||||
// Clear previous children and listeners to re-render fresh
|
||||
const fieldGroup = upsertFieldGroup(field, options);
|
||||
fieldGroup.removeChildren();
|
||||
fieldGroup.off('transform');
|
||||
|
||||
if (isFirstRender) {
|
||||
pageLayer.add(fieldGroup);
|
||||
}
|
||||
|
||||
fieldGroup.off('transform');
|
||||
const fieldRect = upsertFieldRect(field, options);
|
||||
fieldGroup.add(fieldRect);
|
||||
|
||||
const fontSize = radioMeta?.fontSize || DEFAULT_STANDARD_FONT_SIZE;
|
||||
|
||||
// Handle rescaling items during transforms.
|
||||
fieldGroup.on('transform', () => {
|
||||
@ -195,6 +195,8 @@ export const renderRadioFieldElement = (
|
||||
fieldGroup.add(text);
|
||||
});
|
||||
|
||||
createFieldHoverInteraction({ fieldGroup, fieldRect, options });
|
||||
|
||||
return {
|
||||
fieldGroup,
|
||||
isFirstRender,
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
import Konva from 'konva';
|
||||
|
||||
import {
|
||||
DEFAULT_RECT_BACKGROUND,
|
||||
RECIPIENT_COLOR_STYLES,
|
||||
} from '@documenso/ui/lib/recipient-colors';
|
||||
|
||||
import { DEFAULT_SIGNATURE_TEXT_FONT_SIZE } from '../../constants/pdf';
|
||||
import { AppError } from '../../errors/app-error';
|
||||
import { upsertFieldGroup, upsertFieldRect } from './field-generic-items';
|
||||
import {
|
||||
createFieldHoverInteraction,
|
||||
upsertFieldGroup,
|
||||
upsertFieldRect,
|
||||
} from './field-generic-items';
|
||||
import { calculateFieldPosition } from './field-renderer';
|
||||
import type { FieldToRender, RenderFieldElementOptions } from './field-renderer';
|
||||
|
||||
@ -212,33 +211,7 @@ export const renderSignatureFieldElement = (
|
||||
fieldRect.opacity(0);
|
||||
}
|
||||
|
||||
// Todo: Doesn't work.
|
||||
if (mode !== 'export') {
|
||||
const hoverColor = options.color
|
||||
? RECIPIENT_COLOR_STYLES[options.color].baseRingHover
|
||||
: '#e5e7eb';
|
||||
|
||||
// Todo: Envelopes - On hover add text color
|
||||
|
||||
// Add smooth transition-like behavior for hover effects
|
||||
fieldGroup.on('mouseover', () => {
|
||||
new Konva.Tween({
|
||||
node: fieldRect,
|
||||
duration: 0.3,
|
||||
fill: hoverColor,
|
||||
}).play();
|
||||
});
|
||||
|
||||
fieldGroup.on('mouseout', () => {
|
||||
new Konva.Tween({
|
||||
node: fieldRect,
|
||||
duration: 0.3,
|
||||
fill: DEFAULT_RECT_BACKGROUND,
|
||||
}).play();
|
||||
});
|
||||
|
||||
fieldGroup.add(fieldRect);
|
||||
}
|
||||
createFieldHoverInteraction({ fieldGroup, fieldRect, options });
|
||||
|
||||
return {
|
||||
fieldGroup,
|
||||
|
||||
@ -1,13 +1,9 @@
|
||||
import Konva from 'konva';
|
||||
|
||||
import {
|
||||
DEFAULT_RECT_BACKGROUND,
|
||||
RECIPIENT_COLOR_STYLES,
|
||||
} from '@documenso/ui/lib/recipient-colors';
|
||||
|
||||
import { DEFAULT_STANDARD_FONT_SIZE } from '../../constants/pdf';
|
||||
import type { TTextFieldMeta } from '../../types/field-meta';
|
||||
import {
|
||||
createFieldHoverInteraction,
|
||||
konvaTextFill,
|
||||
konvaTextFontFamily,
|
||||
upsertFieldGroup,
|
||||
@ -19,12 +15,12 @@ import { calculateFieldPosition } from './field-renderer';
|
||||
const upsertFieldText = (field: FieldToRender, options: RenderFieldElementOptions): Konva.Text => {
|
||||
const { pageWidth, pageHeight, mode = 'edit', pageLayer, translations } = options;
|
||||
|
||||
const fieldTypeName = translations?.[field.type] || field.type;
|
||||
|
||||
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
|
||||
|
||||
const textMeta = field.fieldMeta as TTextFieldMeta | undefined;
|
||||
|
||||
const fieldTypeName = translations?.[field.type] || field.type;
|
||||
|
||||
const fieldText: Konva.Text =
|
||||
pageLayer.findOne(`#${field.renderId}-text`) ||
|
||||
new Konva.Text({
|
||||
@ -118,9 +114,8 @@ export const renderTextFieldElement = (
|
||||
|
||||
const isFirstRender = !pageLayer.findOne(`#${field.renderId}`);
|
||||
|
||||
const fieldGroup = upsertFieldGroup(field, options);
|
||||
|
||||
// Clear previous children and listeners to re-render fresh.
|
||||
const fieldGroup = upsertFieldGroup(field, options);
|
||||
fieldGroup.removeChildren();
|
||||
fieldGroup.off('transform');
|
||||
|
||||
@ -183,33 +178,7 @@ export const renderTextFieldElement = (
|
||||
fieldRect.opacity(0);
|
||||
}
|
||||
|
||||
// Todo: Doesn't work.
|
||||
if (mode !== 'export') {
|
||||
const hoverColor = options.color
|
||||
? RECIPIENT_COLOR_STYLES[options.color].baseRingHover
|
||||
: '#e5e7eb';
|
||||
|
||||
// Todo: Envelopes - On hover add text color
|
||||
|
||||
// Add smooth transition-like behavior for hover effects
|
||||
fieldGroup.on('mouseover', () => {
|
||||
new Konva.Tween({
|
||||
node: fieldRect,
|
||||
duration: 0.3,
|
||||
fill: hoverColor,
|
||||
}).play();
|
||||
});
|
||||
|
||||
fieldGroup.on('mouseout', () => {
|
||||
new Konva.Tween({
|
||||
node: fieldRect,
|
||||
duration: 0.3,
|
||||
fill: DEFAULT_RECT_BACKGROUND,
|
||||
}).play();
|
||||
});
|
||||
|
||||
fieldGroup.add(fieldRect);
|
||||
}
|
||||
createFieldHoverInteraction({ fieldGroup, fieldRect, options });
|
||||
|
||||
return {
|
||||
fieldGroup,
|
||||
|
||||
Reference in New Issue
Block a user