Files
Voiced/src/pdf/decor/CircledIcon.tsx
T
xavierk 5ea62a9be8 Add the Northline template family: Purple Pop and Citrus Split
Purple Pop (cream page, purple pills, asterisk and dome decor, opt-in
logo) and Citrus Split (grey split panel, halftone chevrons, icon
contacts, logo in the measured slot) are rebuilt from the Canva PDFs on
the engine with A4/Letter support, GST slots and zero audit errors. Adds
static DM Sans, Jost and Poppins 800 as look-alikes for the commercial
fonts. The picker now lists ten templates.
2026-10-04 09:56:56 +05:30

54 lines
1.9 KiB
TypeScript

import { Circle, G, Path, Svg } from "@react-pdf/renderer";
import { ICONS, type IconName } from "./icons.generated";
export interface ContactIconProps {
name: IconName;
/** Side of the square box, pt. */
size: number;
color: string;
}
/** A Carbon icon as a static Svg, filled with `color`. */
export function ContactIcon({ name, size, color }: ContactIconProps) {
const icon = ICONS[name];
return (
<Svg width={size} height={size} viewBox={icon.viewBox}>
{icon.paths.map((d, i) => (
<Path key={i} d={d} fill={color} />
))}
</Svg>
);
}
export interface CircledIconProps extends ContactIconProps {
/** Ring thickness, pt. */
ring: number;
/** The icon's share of the diameter, 0..1. */
glyph?: number;
/** A filled disc with the glyph knocked out in `glyphColor` (default white) instead of a ring. */
solid?: boolean;
glyphColor?: string;
}
/**
* An icon inside a ring (Slate Band's footer): one static Svg, ring and glyph together. The glyph sits in a
* translated and scaled static group (verified to work as a static child, unlike inside a render prop).
*/
export function CircledIcon({ name, size, color, ring, glyph = 0.5, solid = false, glyphColor = "#FFFFFF" }: CircledIconProps) {
const icon = ICONS[name];
const [minX, minY, vw, vh] = icon.viewBox.split(" ").map(Number);
const scale = (size * glyph) / Math.max(vw, vh);
const ox = (size - vw * scale) / 2 - minX * scale;
const oy = (size - vh * scale) / 2 - minY * scale;
return (
<Svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
{solid ? <Circle cx={size / 2} cy={size / 2} r={size / 2} fill={color} /> : <Circle cx={size / 2} cy={size / 2} r={size / 2 - ring / 2} stroke={color} strokeWidth={ring} fill="none" />}
<G transform={`translate(${ox} ${oy}) scale(${scale})`}>
{icon.paths.map((d, i) => (
<Path key={i} d={d} fill={solid ? glyphColor : color} />
))}
</G>
</Svg>
);
}