Skip to main content

Overview

All TypeScript types exported by @sanity-labs/logo-soup. Import them from the main package:
import type {
  LogoSoupEngine,
  LogoSoupState,
  ProcessOptions,
  NormalizedLogo,
  AlignmentMode,
  LogoSource,
  VisualCenter,
  BoundingBox,
  MeasurementResult,
  BackgroundColor,
} from '@sanity-labs/logo-soup';

LogoSoupEngine

The engine interface returned by createLogoSoup().
type LogoSoupEngine = {
  process(options: ProcessOptions): void;
  subscribe(listener: () => void): () => void;
  getSnapshot(): LogoSoupState;
  destroy(): void;
};
process
(options: ProcessOptions) => void
Trigger a processing run. Call when inputs change. Automatically cancels any in-flight work.
subscribe
(listener: () => void) => () => void
Subscribe to state changes. Returns an unsubscribe function.
getSnapshot
() => LogoSoupState
Get the current immutable state snapshot. Returns the same reference if nothing changed.
destroy
() => void
Clean up resources: revoke blob URLs, cancel work, clear cache, remove listeners.
See createLogoSoup for detailed documentation.

LogoSoupState

Immutable state snapshot returned by engine.getSnapshot().
type LogoSoupState = {
  status: 'idle' | 'loading' | 'ready' | 'error';
  normalizedLogos: NormalizedLogo[];
  error: Error | null;
};
status
'idle' | 'loading' | 'ready' | 'error'
required
Current processing status:
  • idle — Initial state before first process() call
  • loading — Loading or measuring images
  • ready — Processing complete, normalized logos available
  • error — All logos failed to load
normalizedLogos
NormalizedLogo[]
required
Array of successfully processed and normalized logos. Empty if not ready or if all failed.
error
Error | null
Error object if status is error, otherwise null.

ProcessOptions

Options passed to engine.process().
type ProcessOptions = {
  logos: (string | LogoSource)[];
  baseSize?: number;
  scaleFactor?: number;
  contrastThreshold?: number;
  densityAware?: boolean;
  densityFactor?: number;
  cropToContent?: boolean;
  backgroundColor?: BackgroundColor;
};
logos
(string | LogoSource)[]
required
Array of logo URLs (strings) or logo objects with src and optional alt text.
logos: [
  '/logo1.svg',
  { src: '/logo2.svg', alt: 'Acme Corp' },
]
baseSize
number
default:"48"
Target size in pixels. All logos are normalized to this approximate size.
scaleFactor
number
default:"0.5"
Shape handling factor (0-1):
  • 0 = Uniform widths (tall logos appear larger)
  • 1 = Uniform heights (wide logos appear larger)
  • 0.5 = Balanced (recommended)
contrastThreshold
number
default:"10"
Minimum contrast (0-255) for content detection. Lower values detect more subtle edges, higher values only detect high-contrast content.
densityAware
boolean
default:"true"
Enable density compensation. When enabled:
  • Dense/bold logos are scaled down
  • Light/thin logos are scaled up
  • Visual center data is computed for alignment
densityFactor
number
default:"0.5"
Strength of density compensation (0-1). Only applies when densityAware: true.
  • 0 = No density adjustment
  • 1 = Full density adjustment
  • 0.5 = Balanced (recommended)
cropToContent
boolean
default:"false"
Automatically crop whitespace/padding from logos. Creates blob URLs for cropped versions.Enable when logos have inconsistent padding baked into the images.
backgroundColor
BackgroundColor
Background color for contrast detection on opaque logos. Can be:
  • CSS color string: '#ffffff', 'rgb(255, 255, 255)', 'hsl(0, 0%, 100%)'
  • RGB tuple: [255, 255, 255]
If omitted, the background is auto-detected from the logo’s corner pixels.

A processed and normalized logo with computed dimensions and metadata.
type NormalizedLogo = {
  src: string;
  alt: string;
  originalWidth: number;
  originalHeight: number;
  contentBox?: BoundingBox;
  normalizedWidth: number;
  normalizedHeight: number;
  aspectRatio: number;
  pixelDensity?: number;
  visualCenter?: VisualCenter;
  croppedSrc?: string;
};
src
string
required
Original logo URL.
alt
string
required
Alt text for accessibility. Empty string if not provided.
originalWidth
number
required
Original image width in pixels.
originalHeight
number
required
Original image height in pixels.
contentBox
BoundingBox
Detected content bounding box (excludes whitespace/padding). Present if content detection found a smaller region than the full image.
normalizedWidth
number
required
Computed width for rendering in pixels, after normalization.
normalizedHeight
number
required
Computed height for rendering in pixels, after normalization.
aspectRatio
number
required
Aspect ratio (width / height) of the content box or original image.
pixelDensity
number
Visual weight density (0-1). Higher values indicate denser/bolder logos. Present when densityAware: true.
visualCenter
VisualCenter
Visual weight center data. Present when densityAware: true and detection succeeded.Use with getVisualCenterTransform() for optical alignment.
croppedSrc
string
Blob URL for the cropped version of the logo. Present when cropToContent: true and content box is smaller than the original.Use this instead of src when rendering to eliminate padding.

Usage Example

const logo: NormalizedLogo = {
  src: '/logos/acme.svg',
  alt: 'Acme Corp',
  originalWidth: 200,
  originalHeight: 100,
  contentBox: { x: 20, y: 10, width: 160, height: 80 },
  normalizedWidth: 96,
  normalizedHeight: 48,
  aspectRatio: 2.0,
  pixelDensity: 0.45,
  visualCenter: { x: 100, y: 50, offsetX: -5, offsetY: 2 },
  croppedSrc: 'blob:http://localhost:3000/abc-123',
};

// Render using normalized dimensions
<img
  src={logo.croppedSrc || logo.src}
  alt={logo.alt}
  width={logo.normalizedWidth}
  height={logo.normalizedHeight}
/>

AlignmentMode

Alignment mode for visual center transforms.
type AlignmentMode =
  | 'bounds'
  | 'visual-center'
  | 'visual-center-x'
  | 'visual-center-y';
bounds
Align by geometric center (bounding box). No transform applied.
visual-center
Align by visual weight center on both X and Y axes.
visual-center-x
Align by visual center horizontally only.
visual-center-y
Align by visual center vertically only. Recommended for horizontal logo strips.
See getVisualCenterTransform for usage details.

LogoSource

Logo input with optional alt text.
type LogoSource = {
  src: string;
  alt?: string;
};
src
string
required
Logo URL. Can be relative, absolute, or a data URL.
alt
string
Alt text for accessibility. If omitted, defaults to empty string.

Usage

// As a string
logos: ['/logo1.svg', '/logo2.svg']

// As LogoSource objects
logos: [
  { src: '/logo1.svg', alt: 'Acme Corp' },
  { src: '/logo2.svg', alt: 'Globex Corporation' },
]

// Mixed
logos: [
  '/logo1.svg',
  { src: '/logo2.svg', alt: 'Globex Corporation' },
]

VisualCenter

Visual weight center data for a logo.
type VisualCenter = {
  x: number;
  y: number;
  offsetX: number;
  offsetY: number;
};
x
number
required
Visual center X coordinate in pixels (relative to the content box or original image).
y
number
required
Visual center Y coordinate in pixels (relative to the content box or original image).
offsetX
number
required
Horizontal offset in pixels from the geometric center. Negative = visual center is left of geometric center.
offsetY
number
required
Vertical offset in pixels from the geometric center. Negative = visual center is above geometric center.

BoundingBox

Rectangular region in pixels.
type BoundingBox = {
  x: number;
  y: number;
  width: number;
  height: number;
};
x
number
required
Left edge X coordinate in pixels.
y
number
required
Top edge Y coordinate in pixels.
width
number
required
Width in pixels.
height
number
required
Height in pixels.

MeasurementResult

Raw measurement data for a logo (internal).
type MeasurementResult = {
  width: number;
  height: number;
  contentBox?: BoundingBox;
  pixelDensity?: number;
  visualCenter?: VisualCenter;
  backgroundLuminance?: number;
};
width
number
required
Original image width.
height
number
required
Original image height.
contentBox
BoundingBox
Detected content region (if smaller than full image).
pixelDensity
number
Visual weight density (0-1).
visualCenter
VisualCenter
Visual weight center data.
backgroundLuminance
number
Detected background luminance (0-255). Used for irradiation compensation.
This type is primarily for internal use. You’ll typically work with NormalizedLogo instead.

BackgroundColor

Background color for contrast detection.
type BackgroundColor = CSSColor | [number, number, number];

type CSSColor = HexColor | RGBFunction | HSLFunction | (string & {});
type HexColor = `#${string}`;
type RGBFunction = `rgb(${string})` | `rgba(${string})`;
type HSLFunction = `hsl(${string})` | `hsla(${string})`;

Accepted Formats

Hex color
string
backgroundColor: '#ffffff'
backgroundColor: '#fff'
RGB/RGBA function
string
backgroundColor: 'rgb(255, 255, 255)'
backgroundColor: 'rgba(255, 255, 255, 1)'
HSL/HSLA function
string
backgroundColor: 'hsl(0, 0%, 100%)'
backgroundColor: 'hsla(0, 0%, 100%, 1)'
RGB tuple
[number, number, number]
backgroundColor: [255, 255, 255]
Any CSS color
string
backgroundColor: 'white'
backgroundColor: 'currentColor'
Any valid CSS color string is accepted, though not all are type-safe.

Usage

engine.process({
  logos: ['/logo1.svg'],
  backgroundColor: '#1a1a1a', // Dark background
});

engine.process({
  logos: ['/logo2.svg'],
  backgroundColor: [255, 255, 255], // White background as RGB tuple
});
If omitted, the background color is auto-detected from the logo’s corner pixels.

Build docs developers (and LLMs) love