feat(email-signature): wire SDT/US branding, address selector, color palettes, improved preview
- Per-company branding for Urban Switch and Studii de Teren (logos, websites, mottos) - Beletage address selector (Str. Unirii vs Str. G-ral Eremia Grigorescu) - Company-specific color palettes in configurator - Scrollable preview with multi-level zoom (0.75x to 2.5x) - Address override support in signature config Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,7 @@ import { RotateCcw } from 'lucide-react';
|
|||||||
export function EmailSignatureModule() {
|
export function EmailSignatureModule() {
|
||||||
const {
|
const {
|
||||||
config, updateField, updateColor, updateLayout,
|
config, updateField, updateColor, updateLayout,
|
||||||
setVariant, setCompany, resetToDefaults, loadConfig,
|
setVariant, setCompany, setAddress, resetToDefaults, loadConfig,
|
||||||
} = useSignatureConfig();
|
} = useSignatureConfig();
|
||||||
|
|
||||||
const { saved, loading, save, remove } = useSavedSignatures();
|
const { saved, loading, save, remove } = useSavedSignatures();
|
||||||
@@ -28,6 +28,7 @@ export function EmailSignatureModule() {
|
|||||||
onUpdateLayout={updateLayout}
|
onUpdateLayout={updateLayout}
|
||||||
onSetVariant={setVariant}
|
onSetVariant={setVariant}
|
||||||
onSetCompany={setCompany}
|
onSetCompany={setCompany}
|
||||||
|
onSetAddress={setAddress}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Separator />
|
<Separator />
|
||||||
@@ -49,7 +50,7 @@ export function EmailSignatureModule() {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right panel — preview */}
|
{/* Right panel — preview (scrollable, resizable) */}
|
||||||
<div>
|
<div>
|
||||||
<SignaturePreview config={config} />
|
<SignaturePreview config={config} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import type { CompanyId } from '@/core/auth/types';
|
import type { CompanyId } from '@/core/auth/types';
|
||||||
import type { SignatureConfig, SignatureColors, SignatureLayout, SignatureVariant } from '../types';
|
import type { SignatureConfig, SignatureColors, SignatureLayout, SignatureVariant } from '../types';
|
||||||
import { COMPANY_BRANDING } from '../services/company-branding';
|
import { COMPANY_BRANDING, BELETAGE_ADDRESSES } from '../services/company-branding';
|
||||||
import { Input } from '@/shared/components/ui/input';
|
import { Input } from '@/shared/components/ui/input';
|
||||||
import { Label } from '@/shared/components/ui/label';
|
import { Label } from '@/shared/components/ui/label';
|
||||||
import { Switch } from '@/shared/components/ui/switch';
|
import { Switch } from '@/shared/components/ui/switch';
|
||||||
@@ -17,13 +17,39 @@ interface SignatureConfiguratorProps {
|
|||||||
onUpdateLayout: (key: keyof SignatureLayout, value: number) => void;
|
onUpdateLayout: (key: keyof SignatureLayout, value: number) => void;
|
||||||
onSetVariant: (variant: SignatureVariant) => void;
|
onSetVariant: (variant: SignatureVariant) => void;
|
||||||
onSetCompany: (company: CompanyId) => void;
|
onSetCompany: (company: CompanyId) => void;
|
||||||
|
onSetAddress?: (address: string[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const COLOR_PALETTE: Record<string, string> = {
|
/** Color palette per company */
|
||||||
verde: '#22B5AB',
|
const COMPANY_PALETTES: Record<CompanyId, Record<string, string>> = {
|
||||||
griInchis: '#54504F',
|
beletage: {
|
||||||
griDeschis: '#A7A9AA',
|
verde: '#22B5AB',
|
||||||
negru: '#323232',
|
griInchis: '#54504F',
|
||||||
|
griDeschis: '#A7A9AA',
|
||||||
|
negru: '#323232',
|
||||||
|
},
|
||||||
|
'urban-switch': {
|
||||||
|
indigo: '#6366f1',
|
||||||
|
violet: '#4F46E5',
|
||||||
|
griInchis: '#2D2D2D',
|
||||||
|
griDeschis: '#6B7280',
|
||||||
|
albastru: '#3B82F6',
|
||||||
|
negru: '#1F2937',
|
||||||
|
},
|
||||||
|
'studii-de-teren': {
|
||||||
|
amber: '#f59e0b',
|
||||||
|
portocaliu: '#D97706',
|
||||||
|
griInchis: '#2D2D2D',
|
||||||
|
griDeschis: '#6B7280',
|
||||||
|
maro: '#92400E',
|
||||||
|
negru: '#1F2937',
|
||||||
|
},
|
||||||
|
group: {
|
||||||
|
gri: '#64748b',
|
||||||
|
griInchis: '#334155',
|
||||||
|
griDeschis: '#94a3b8',
|
||||||
|
negru: '#1e293b',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const COLOR_LABELS: Record<keyof SignatureColors, string> = {
|
const COLOR_LABELS: Record<keyof SignatureColors, string> = {
|
||||||
@@ -48,8 +74,10 @@ const LAYOUT_CONTROLS: { key: keyof SignatureLayout; label: string; min: number;
|
|||||||
];
|
];
|
||||||
|
|
||||||
export function SignatureConfigurator({
|
export function SignatureConfigurator({
|
||||||
config, onUpdateField, onUpdateColor, onUpdateLayout, onSetVariant, onSetCompany,
|
config, onUpdateField, onUpdateColor, onUpdateLayout, onSetVariant, onSetCompany, onSetAddress,
|
||||||
}: SignatureConfiguratorProps) {
|
}: SignatureConfiguratorProps) {
|
||||||
|
const palette = COMPANY_PALETTES[config.company];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* Company selector */}
|
{/* Company selector */}
|
||||||
@@ -67,6 +95,26 @@ export function SignatureConfigurator({
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Address selector (for Beletage) */}
|
||||||
|
{config.company === 'beletage' && onSetAddress && (
|
||||||
|
<div>
|
||||||
|
<Label>Adresă birou</Label>
|
||||||
|
<Select
|
||||||
|
value={!config.addressOverride || BELETAGE_ADDRESSES.unirii.join('|') === config.addressOverride.join('|') ? 'unirii' : 'christescu'}
|
||||||
|
onValueChange={(v) => {
|
||||||
|
const key = v as keyof typeof BELETAGE_ADDRESSES;
|
||||||
|
onSetAddress(BELETAGE_ADDRESSES[key]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="mt-1"><SelectValue /></SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="unirii">Str. Unirii, nr. 3</SelectItem>
|
||||||
|
<SelectItem value="christescu">Str. G-ral Eremia Grigorescu, nr. 21</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
||||||
{/* Personal data */}
|
{/* Personal data */}
|
||||||
@@ -113,14 +161,14 @@ export function SignatureConfigurator({
|
|||||||
|
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
||||||
{/* Colors */}
|
{/* Colors — company-specific palette */}
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<h3 className="text-sm font-semibold">Culori text</h3>
|
<h3 className="text-sm font-semibold">Culori text</h3>
|
||||||
{(Object.keys(COLOR_LABELS) as (keyof SignatureColors)[]).map((colorKey) => (
|
{(Object.keys(COLOR_LABELS) as (keyof SignatureColors)[]).map((colorKey) => (
|
||||||
<div key={colorKey} className="flex items-center justify-between">
|
<div key={colorKey} className="flex items-center justify-between">
|
||||||
<span className="text-sm text-muted-foreground">{COLOR_LABELS[colorKey]}</span>
|
<span className="text-sm text-muted-foreground">{COLOR_LABELS[colorKey]}</span>
|
||||||
<div className="flex gap-1.5">
|
<div className="flex gap-1.5">
|
||||||
{Object.values(COLOR_PALETTE).map((color) => (
|
{Object.values(palette).map((color) => (
|
||||||
<button
|
<button
|
||||||
key={color}
|
key={color}
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -6,15 +6,19 @@ import { Button } from '@/shared/components/ui/button';
|
|||||||
import type { SignatureConfig } from '../types';
|
import type { SignatureConfig } from '../types';
|
||||||
import { generateSignatureHtml, downloadSignatureHtml } from '../services/signature-builder';
|
import { generateSignatureHtml, downloadSignatureHtml } from '../services/signature-builder';
|
||||||
|
|
||||||
|
const ZOOM_LEVELS = [0.75, 1, 1.5, 2, 2.5];
|
||||||
|
|
||||||
interface SignaturePreviewProps {
|
interface SignaturePreviewProps {
|
||||||
config: SignatureConfig;
|
config: SignatureConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SignaturePreview({ config }: SignaturePreviewProps) {
|
export function SignaturePreview({ config }: SignaturePreviewProps) {
|
||||||
const [zoom, setZoom] = useState(1);
|
const [zoomIndex, setZoomIndex] = useState(1); // start at 100%
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
const previewRef = useRef<HTMLDivElement>(null);
|
const previewRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const zoom = ZOOM_LEVELS[zoomIndex] ?? 1;
|
||||||
|
|
||||||
const html = useMemo(() => generateSignatureHtml(config), [config]);
|
const html = useMemo(() => generateSignatureHtml(config), [config]);
|
||||||
|
|
||||||
const handleDownload = () => {
|
const handleDownload = () => {
|
||||||
@@ -32,17 +36,23 @@ export function SignaturePreview({ config }: SignaturePreviewProps) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleZoom = () => setZoom((z) => (z === 1 ? 2 : 1));
|
const zoomIn = () => setZoomIndex((i) => Math.min(i + 1, ZOOM_LEVELS.length - 1));
|
||||||
|
const zoomOut = () => setZoomIndex((i) => Math.max(i - 1, 0));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h2 className="text-lg font-semibold">Previzualizare</h2>
|
<h2 className="text-lg font-semibold">Previzualizare</h2>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Button variant="outline" size="sm" onClick={toggleZoom}>
|
<div className="flex items-center rounded-md border">
|
||||||
{zoom === 1 ? <ZoomIn className="mr-1 h-4 w-4" /> : <ZoomOut className="mr-1 h-4 w-4" />}
|
<Button variant="ghost" size="icon" className="h-8 w-8 rounded-r-none" onClick={zoomOut} disabled={zoomIndex <= 0}>
|
||||||
{zoom === 1 ? '200%' : '100%'}
|
<ZoomOut className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
<span className="w-14 text-center text-sm font-medium">{Math.round(zoom * 100)}%</span>
|
||||||
|
<Button variant="ghost" size="icon" className="h-8 w-8 rounded-l-none" onClick={zoomIn} disabled={zoomIndex >= ZOOM_LEVELS.length - 1}>
|
||||||
|
<ZoomIn className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
<Button variant="outline" size="sm" onClick={handleCopy}>
|
<Button variant="outline" size="sm" onClick={handleCopy}>
|
||||||
<Copy className="mr-1 h-4 w-4" />
|
<Copy className="mr-1 h-4 w-4" />
|
||||||
{copied ? 'Copiat!' : 'Copiază HTML'}
|
{copied ? 'Copiat!' : 'Copiază HTML'}
|
||||||
@@ -54,7 +64,7 @@ export function SignaturePreview({ config }: SignaturePreviewProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="overflow-auto rounded-lg border bg-white p-6">
|
<div className="max-h-[calc(100vh-14rem)] overflow-auto rounded-lg border bg-white p-6">
|
||||||
<div
|
<div
|
||||||
ref={previewRef}
|
ref={previewRef}
|
||||||
style={{ transform: `scale(${zoom})`, transformOrigin: 'top left' }}
|
style={{ transform: `scale(${zoom})`, transformOrigin: 'top left' }}
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ export function useSignatureConfig(initialCompany: CompanyId = 'beletage') {
|
|||||||
}));
|
}));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const setAddress = useCallback((address: string[]) => {
|
||||||
|
setConfig((prev) => ({ ...prev, addressOverride: address }));
|
||||||
|
}, []);
|
||||||
|
|
||||||
const resetToDefaults = useCallback(() => {
|
const resetToDefaults = useCallback(() => {
|
||||||
setConfig(createDefaultConfig(config.company));
|
setConfig(createDefaultConfig(config.company));
|
||||||
}, [config.company]);
|
}, [config.company]);
|
||||||
@@ -83,7 +87,8 @@ export function useSignatureConfig(initialCompany: CompanyId = 'beletage') {
|
|||||||
updateLayout,
|
updateLayout,
|
||||||
setVariant,
|
setVariant,
|
||||||
setCompany,
|
setCompany,
|
||||||
|
setAddress,
|
||||||
resetToDefaults,
|
resetToDefaults,
|
||||||
loadConfig,
|
loadConfig,
|
||||||
}), [config, updateField, updateColor, updateLayout, setVariant, setCompany, resetToDefaults, loadConfig]);
|
}), [config, updateField, updateColor, updateLayout, setVariant, setCompany, setAddress, resetToDefaults, loadConfig]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,25 +12,34 @@ const BELETAGE_COLORS: SignatureColors = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const URBAN_SWITCH_COLORS: SignatureColors = {
|
const URBAN_SWITCH_COLORS: SignatureColors = {
|
||||||
prefix: '#3B3B3B',
|
prefix: '#2D2D2D',
|
||||||
name: '#3B3B3B',
|
name: '#2D2D2D',
|
||||||
title: '#8B8B8B',
|
title: '#6B7280',
|
||||||
address: '#8B8B8B',
|
address: '#6B7280',
|
||||||
phone: '#3B3B3B',
|
phone: '#2D2D2D',
|
||||||
website: '#3B3B3B',
|
website: '#4F46E5',
|
||||||
motto: '#6366f1',
|
motto: '#6366f1',
|
||||||
};
|
};
|
||||||
|
|
||||||
const STUDII_COLORS: SignatureColors = {
|
const STUDII_COLORS: SignatureColors = {
|
||||||
prefix: '#3B3B3B',
|
prefix: '#2D2D2D',
|
||||||
name: '#3B3B3B',
|
name: '#2D2D2D',
|
||||||
title: '#8B8B8B',
|
title: '#6B7280',
|
||||||
address: '#8B8B8B',
|
address: '#6B7280',
|
||||||
phone: '#3B3B3B',
|
phone: '#2D2D2D',
|
||||||
website: '#3B3B3B',
|
website: '#D97706',
|
||||||
motto: '#f59e0b',
|
motto: '#f59e0b',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ADDR_UNIRII = ['str. Unirii, nr. 3, ap. 26', 'Cluj-Napoca, Cluj 400417', 'România'] as const;
|
||||||
|
const ADDR_CHRISTESCU = ['str. G-ral Eremia Grigorescu, nr. 21', 'Cluj-Napoca, Cluj 400304', 'România'] as const;
|
||||||
|
|
||||||
|
/** Available address options for Beletage (toggle between offices) */
|
||||||
|
export const BELETAGE_ADDRESSES: { unirii: string[]; christescu: string[] } = {
|
||||||
|
unirii: [...ADDR_UNIRII],
|
||||||
|
christescu: [...ADDR_CHRISTESCU],
|
||||||
|
};
|
||||||
|
|
||||||
export const COMPANY_BRANDING: Record<CompanyId, CompanyBranding> = {
|
export const COMPANY_BRANDING: Record<CompanyId, CompanyBranding> = {
|
||||||
beletage: {
|
beletage: {
|
||||||
id: 'beletage',
|
id: 'beletage',
|
||||||
@@ -48,7 +57,7 @@ export const COMPANY_BRANDING: Record<CompanyId, CompanyBranding> = {
|
|||||||
png: 'https://beletage.ro/img/Green-slash.png',
|
png: 'https://beletage.ro/img/Green-slash.png',
|
||||||
svg: 'https://beletage.ro/img/Green-slash.svg',
|
svg: 'https://beletage.ro/img/Green-slash.svg',
|
||||||
},
|
},
|
||||||
address: ['str. Unirii, nr. 3, ap. 26', 'Cluj-Napoca, Cluj 400417', 'România'],
|
address: [...ADDR_UNIRII],
|
||||||
website: 'www.beletage.ro',
|
website: 'www.beletage.ro',
|
||||||
motto: 'we make complex simple',
|
motto: 'we make complex simple',
|
||||||
defaultColors: BELETAGE_COLORS,
|
defaultColors: BELETAGE_COLORS,
|
||||||
@@ -58,20 +67,20 @@ export const COMPANY_BRANDING: Record<CompanyId, CompanyBranding> = {
|
|||||||
name: 'Urban Switch SRL',
|
name: 'Urban Switch SRL',
|
||||||
accent: '#6366f1',
|
accent: '#6366f1',
|
||||||
logo: {
|
logo: {
|
||||||
png: '',
|
png: '/logos/logo-us-dark.svg',
|
||||||
svg: '',
|
svg: '/logos/logo-us-dark.svg',
|
||||||
},
|
},
|
||||||
slashGrey: {
|
slashGrey: {
|
||||||
png: 'https://beletage.ro/img/Grey-slash.png',
|
png: 'https://beletage.ro/img/Grey-slash.png',
|
||||||
svg: 'https://beletage.ro/img/Grey-slash.svg',
|
svg: 'https://beletage.ro/img/Grey-slash.svg',
|
||||||
},
|
},
|
||||||
slashAccent: {
|
slashAccent: {
|
||||||
png: '',
|
png: '/logos/logo-us-light.svg',
|
||||||
svg: '',
|
svg: '/logos/logo-us-light.svg',
|
||||||
},
|
},
|
||||||
address: ['Cluj-Napoca', 'România'],
|
address: ['str. Unirii, nr. 3, ap. 26', 'Cluj-Napoca, Cluj 400417', 'România'],
|
||||||
website: '',
|
website: 'www.urbanswitch.ro',
|
||||||
motto: '',
|
motto: 'shaping urban futures',
|
||||||
defaultColors: URBAN_SWITCH_COLORS,
|
defaultColors: URBAN_SWITCH_COLORS,
|
||||||
},
|
},
|
||||||
'studii-de-teren': {
|
'studii-de-teren': {
|
||||||
@@ -79,20 +88,20 @@ export const COMPANY_BRANDING: Record<CompanyId, CompanyBranding> = {
|
|||||||
name: 'Studii de Teren SRL',
|
name: 'Studii de Teren SRL',
|
||||||
accent: '#f59e0b',
|
accent: '#f59e0b',
|
||||||
logo: {
|
logo: {
|
||||||
png: '',
|
png: '/logos/logo-sdt-dark.svg',
|
||||||
svg: '',
|
svg: '/logos/logo-sdt-dark.svg',
|
||||||
},
|
},
|
||||||
slashGrey: {
|
slashGrey: {
|
||||||
png: 'https://beletage.ro/img/Grey-slash.png',
|
png: 'https://beletage.ro/img/Grey-slash.png',
|
||||||
svg: 'https://beletage.ro/img/Grey-slash.svg',
|
svg: 'https://beletage.ro/img/Grey-slash.svg',
|
||||||
},
|
},
|
||||||
slashAccent: {
|
slashAccent: {
|
||||||
png: '',
|
png: '/logos/logo-sdt-light.svg',
|
||||||
svg: '',
|
svg: '/logos/logo-sdt-light.svg',
|
||||||
},
|
},
|
||||||
address: ['Cluj-Napoca', 'România'],
|
address: ['str. Unirii, nr. 3, ap. 26', 'Cluj-Napoca, Cluj 400417', 'România'],
|
||||||
website: '',
|
website: 'www.studiideteren.ro',
|
||||||
motto: '',
|
motto: 'ground truth, measured right',
|
||||||
defaultColors: STUDII_COLORS,
|
defaultColors: STUDII_COLORS,
|
||||||
},
|
},
|
||||||
group: {
|
group: {
|
||||||
@@ -100,9 +109,12 @@ export const COMPANY_BRANDING: Record<CompanyId, CompanyBranding> = {
|
|||||||
name: 'Grup Companii',
|
name: 'Grup Companii',
|
||||||
accent: '#64748b',
|
accent: '#64748b',
|
||||||
logo: { png: '', svg: '' },
|
logo: { png: '', svg: '' },
|
||||||
slashGrey: { png: '', svg: '' },
|
slashGrey: {
|
||||||
|
png: 'https://beletage.ro/img/Grey-slash.png',
|
||||||
|
svg: 'https://beletage.ro/img/Grey-slash.svg',
|
||||||
|
},
|
||||||
slashAccent: { png: '', svg: '' },
|
slashAccent: { png: '', svg: '' },
|
||||||
address: ['Cluj-Napoca', 'România'],
|
address: ['Cluj-Napoca, Cluj', 'România'],
|
||||||
website: '',
|
website: '',
|
||||||
motto: '',
|
motto: '',
|
||||||
defaultColors: BELETAGE_COLORS,
|
defaultColors: BELETAGE_COLORS,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export function formatPhone(raw: string): { display: string; link: string } {
|
|||||||
|
|
||||||
export function generateSignatureHtml(config: SignatureConfig): string {
|
export function generateSignatureHtml(config: SignatureConfig): string {
|
||||||
const branding = getBranding(config.company);
|
const branding = getBranding(config.company);
|
||||||
|
const address = config.addressOverride ?? branding.address;
|
||||||
const { display: phone, link: phoneLink } = formatPhone(config.phone);
|
const { display: phone, link: phoneLink } = formatPhone(config.phone);
|
||||||
const images = config.useSvg
|
const images = config.useSvg
|
||||||
? { logo: branding.logo.svg, greySlash: branding.slashGrey.svg, accentSlash: branding.slashAccent.svg }
|
? { logo: branding.logo.svg, greySlash: branding.slashGrey.svg, accentSlash: branding.slashAccent.svg }
|
||||||
@@ -71,7 +72,7 @@ export function generateSignatureHtml(config: SignatureConfig): string {
|
|||||||
</td>
|
</td>
|
||||||
<td width="${spacerWidth}" style="width:${spacerWidth}px; font-size:0; line-height:0;"></td>
|
<td width="${spacerWidth}" style="width:${spacerWidth}px; font-size:0; line-height:0;"></td>
|
||||||
<td style="vertical-align:top; padding:0 0 0 ${textPaddingLeft}px;">
|
<td style="vertical-align:top; padding:0 0 0 ${textPaddingLeft}px;">
|
||||||
<span style="color:${colors.address}; text-decoration:none;">${branding.address.join('<br>')}</span>
|
<span style="color:${colors.address}; text-decoration:none;">${address.join('<br>')}</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ export interface SignatureConfig {
|
|||||||
layout: SignatureLayout;
|
layout: SignatureLayout;
|
||||||
variant: SignatureVariant;
|
variant: SignatureVariant;
|
||||||
useSvg: boolean;
|
useSvg: boolean;
|
||||||
|
/** Override the default company address */
|
||||||
|
addressOverride?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SavedSignature {
|
export interface SavedSignature {
|
||||||
|
|||||||
Reference in New Issue
Block a user