/**
* Convert Figma effects (shadows, blurs) to CSS.
*/
import {colorToCSS, type FigmaColor} from './color.js';
export interface FigmaEffect {
type: string;
visible?: boolean;
radius: number;
color?: FigmaColor;
offset?: {x: number; y: number};
spread?: number;
}
export interface EffectsCSS {
boxShadow?: string;
filter?: string;
backdropFilter?: string;
}
function shadowToCSS(effect: FigmaEffect, inset: boolean): string {
const x = effect.offset?.x ?? 0;
const y = effect.offset?.y ?? 0;
const blur = effect.radius;
const spread = effect.spread ?? 0;
const color = effect.color ? colorToCSS(effect.color) : 'rgba(0, 0, 0, 0.25)';
const insetStr = inset ? 'inset ' : '';
return `${insetStr}${x}px ${y}px ${blur}px ${spread}px ${color}`;
}
/**
* Extract CSS effects from Figma effects array.
* Returns undefined if there are no visible effects.
*/
export function extractEffects(effects: FigmaEffect[]): EffectsCSS | undefined {
if (!effects?.length) return undefined;
const shadows: string[] = [];
const filters: string[] = [];
const backdropFilters: string[] = [];
for (const effect of effects) {
if (effect.visible === false) continue;
switch (effect.type) {
case 'DROP_SHADOW':
shadows.push(shadowToCSS(effect, false));
break;
case 'INNER_SHADOW':
shadows.push(shadowToCSS(effect, true));
break;
case 'LAYER_BLUR':
filters.push(`blur(${effect.radius}px)`);
break;
case 'BACKGROUND_BLUR':
backdropFilters.push(`blur(${effect.radius}px)`);
break;
}
}
const result: EffectsCSS = {};
if (shadows.length) result.boxShadow = shadows.join(', ');
if (filters.length) result.filter = filters.join(' ');
if (backdropFilters.length) result.backdropFilter = backdropFilters.join(' ');
return Object.keys(result).length > 0 ? result : undefined;
}