0
Fork 0
mirror of https://github.com/penpot/penpot-exporter-figma-plugin.git synced 2024-12-22 05:33:02 -05:00

Add shadows to the export (#58)

This commit is contained in:
Jordi Sala Morales 2024-04-22 14:35:59 +02:00 committed by GitHub
parent c464ff9bda
commit e732887399
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 94 additions and 15 deletions

View file

@ -0,0 +1,5 @@
---
"penpot-exporter": minor
---
Shadows

View file

@ -2,6 +2,7 @@ export * from './transformBlend';
export * from './transformChildren'; export * from './transformChildren';
export * from './transformCornerRadius'; export * from './transformCornerRadius';
export * from './transformDimensionAndPosition'; export * from './transformDimensionAndPosition';
export * from './transformEffects';
export * from './transformFills'; export * from './transformFills';
export * from './transformProportion'; export * from './transformProportion';
export * from './transformSceneNode'; export * from './transformSceneNode';

View file

@ -0,0 +1,9 @@
import { translateShadowEffects } from '@plugin/translators';
import { ShapeAttributes } from '@ui/lib/types/shape/shapeAttributes';
export const transformEffects = (node: BlendMixin): Partial<ShapeAttributes> => {
return {
shadow: translateShadowEffects(node.effects)
};
};

View file

@ -1,6 +1,7 @@
import { import {
transformBlend, transformBlend,
transformDimensionAndPosition, transformDimensionAndPosition,
transformEffects,
transformFills, transformFills,
transformProportion, transformProportion,
transformSceneNode, transformSceneNode,
@ -18,6 +19,7 @@ export const transformEllipseNode = (
type: 'circle', type: 'circle',
name: node.name, name: node.name,
...transformFills(node), ...transformFills(node),
...transformEffects(node),
...transformStrokes(node), ...transformStrokes(node),
...transformDimensionAndPosition(node, baseX, baseY), ...transformDimensionAndPosition(node, baseX, baseY),
...transformSceneNode(node), ...transformSceneNode(node),

View file

@ -3,6 +3,7 @@ import {
transformChildren, transformChildren,
transformCornerRadius, transformCornerRadius,
transformDimensionAndPosition, transformDimensionAndPosition,
transformEffects,
transformFills, transformFills,
transformProportion, transformProportion,
transformSceneNode, transformSceneNode,
@ -20,25 +21,30 @@ export const transformFrameNode = async (
baseX: number, baseX: number,
baseY: number baseY: number
): Promise<FrameShape> => { ): Promise<FrameShape> => {
let frameSpecificAttributes: Partial<FrameShape> = {};
if (!isSectionNode(node)) {
// Figma API does not expose strokes, blend modes, corner radius, or constraint proportions for sections,
// they plan to add it in the future. Refactor this when available.
frameSpecificAttributes = {
// @see: https://forum.figma.com/t/why-are-strokes-not-available-on-section-nodes/41658
...transformStrokes(node),
// @see: https://forum.figma.com/t/add-a-blendmode-property-for-sectionnode/58560
...transformBlend(node),
...transformProportion(node),
...transformCornerRadius(node),
...transformEffects(node)
};
}
return { return {
type: 'frame', type: 'frame',
name: node.name, name: node.name,
showContent: isSectionNode(node) ? true : !node.clipsContent, showContent: isSectionNode(node) ? true : !node.clipsContent,
...transformFills(node), ...transformFills(node),
// Figma API does not expose strokes for sections, ...frameSpecificAttributes,
// they plan to add it in the future. Refactor this when available.
// @see: https://forum.figma.com/t/why-are-strokes-not-available-on-section-nodes/41658
...(isSectionNode(node) ? [] : transformStrokes(node)),
...(await transformChildren(node, baseX + node.x, baseY + node.y)), ...(await transformChildren(node, baseX + node.x, baseY + node.y)),
...transformDimensionAndPosition(node, baseX, baseY), ...transformDimensionAndPosition(node, baseX, baseY),
// Figma API does not expose blend modes for sections, ...transformSceneNode(node)
// they plan to add it in the future. Refactor this when available.
// @see: https://forum.figma.com/t/add-a-blendmode-property-for-sectionnode/58560
...(isSectionNode(node) ? [] : transformBlend(node)),
...transformSceneNode(node),
// Figma API does not expose constraints proportions for sections
...(isSectionNode(node) ? [] : transformProportion(node)),
// Figma API does not expose corner radius for sections
...(isSectionNode(node) ? [] : transformCornerRadius(node))
}; };
}; };

View file

@ -1,6 +1,7 @@
import { import {
transformBlend, transformBlend,
transformDimensionAndPosition, transformDimensionAndPosition,
transformEffects,
transformSceneNode transformSceneNode
} from '@plugin/transformers/partials'; } from '@plugin/transformers/partials';
import { transformChildren } from '@plugin/transformers/partials'; import { transformChildren } from '@plugin/transformers/partials';
@ -17,6 +18,7 @@ export const transformGroupNode = async (
name: node.name, name: node.name,
...(await transformChildren(node, baseX, baseY)), ...(await transformChildren(node, baseX, baseY)),
...transformDimensionAndPosition(node, baseX, baseY), ...transformDimensionAndPosition(node, baseX, baseY),
...transformEffects(node),
...transformSceneNode(node), ...transformSceneNode(node),
...transformBlend(node) ...transformBlend(node)
}; };

View file

@ -1,6 +1,7 @@
import { import {
transformBlend, transformBlend,
transformDimensionAndPosition, transformDimensionAndPosition,
transformEffects,
transformFills, transformFills,
transformProportion, transformProportion,
transformSceneNode, transformSceneNode,
@ -23,6 +24,7 @@ export const transformPathNode = (
name: node.name, name: node.name,
...(hasFillGeometry(node) ? transformFills(node) : []), ...(hasFillGeometry(node) ? transformFills(node) : []),
...transformStrokes(node), ...transformStrokes(node),
...transformEffects(node),
...transformVectorPaths(node, baseX, baseY), ...transformVectorPaths(node, baseX, baseY),
...transformDimensionAndPosition(node, baseX, baseY), ...transformDimensionAndPosition(node, baseX, baseY),
...transformSceneNode(node), ...transformSceneNode(node),

View file

@ -2,6 +2,7 @@ import {
transformBlend, transformBlend,
transformCornerRadius, transformCornerRadius,
transformDimensionAndPosition, transformDimensionAndPosition,
transformEffects,
transformFills, transformFills,
transformProportion, transformProportion,
transformSceneNode, transformSceneNode,
@ -19,6 +20,7 @@ export const transformRectangleNode = (
type: 'rect', type: 'rect',
name: node.name, name: node.name,
...transformFills(node), ...transformFills(node),
...transformEffects(node),
...transformStrokes(node), ...transformStrokes(node),
...transformDimensionAndPosition(node, baseX, baseY), ...transformDimensionAndPosition(node, baseX, baseY),
...transformSceneNode(node), ...transformSceneNode(node),

View file

@ -1,6 +1,7 @@
import { import {
transformBlend, transformBlend,
transformDimensionAndPosition, transformDimensionAndPosition,
transformEffects,
transformFills, transformFills,
transformProportion, transformProportion,
transformSceneNode, transformSceneNode,
@ -42,6 +43,7 @@ export const transformTextNode = (node: TextNode, baseX: number, baseY: number):
] ]
}, },
...transformDimensionAndPosition(node, baseX, baseY), ...transformDimensionAndPosition(node, baseX, baseY),
...transformEffects(node),
...transformSceneNode(node), ...transformSceneNode(node),
...transformBlend(node), ...transformBlend(node),
...transformProportion(node) ...transformProportion(node)

View file

@ -1,4 +1,5 @@
export * from './translateBlendMode'; export * from './translateBlendMode';
export * from './translateShadowEffects';
export * from './translateFills'; export * from './translateFills';
export * from './translateStrokes'; export * from './translateStrokes';
export * from './translateStyledTextSegments'; export * from './translateStyledTextSegments';

View file

@ -0,0 +1,45 @@
import { rgbToHex } from '@plugin/utils';
import { Shadow, ShadowStyle } from '@ui/lib/types/utils/shadow';
export const translateShadowEffect = (effect: Effect): Shadow | undefined => {
if (effect.type !== 'DROP_SHADOW' && effect.type !== 'INNER_SHADOW') {
return;
}
return {
style: translateShadowType(effect),
offsetX: effect.offset.x,
offsetY: effect.offset.y,
blur: effect.radius,
spread: effect.spread ?? 0,
hidden: !effect.visible,
color: {
color: rgbToHex(effect.color),
opacity: effect.color.a
}
};
};
export const translateShadowEffects = (effects: readonly Effect[]): Shadow[] => {
const shadows: Shadow[] = [];
for (const effect of effects) {
const shadow = translateShadowEffect(effect);
if (shadow) {
// effects are applied in reverse order in Figma, that's why we unshift
shadows.unshift(shadow);
}
}
return shadows;
};
const translateShadowType = (effect: DropShadowEffect | InnerShadowEffect): ShadowStyle => {
switch (effect.type) {
case 'DROP_SHADOW':
return 'drop-shadow';
case 'INNER_SHADOW':
return 'inner-shadow';
}
};

View file

@ -12,6 +12,6 @@ export type Color = {
modifiedAt?: string; //@TODO: check this attribute in penpot modifiedAt?: string; //@TODO: check this attribute in penpot
refId?: Uuid; refId?: Uuid;
refFile?: Uuid; refFile?: Uuid;
gradient: Gradient; gradient?: Gradient;
image?: ImageColor; image?: ImageColor;
}; };

View file

@ -2,9 +2,11 @@ import { Color } from '@ui/lib/types/utils/color';
import { Uuid } from './uuid'; import { Uuid } from './uuid';
export type ShadowStyle = 'drop-shadow' | 'inner-shadow';
export type Shadow = { export type Shadow = {
id?: Uuid; id?: Uuid;
style: symbol; // 'drop-shadow' | 'inner-shadow' style: ShadowStyle;
offsetX: number; offsetX: number;
offsetY: number; offsetY: number;
blur: number; blur: number;