Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autolayout #151

Merged
merged 13 commits into from
Jun 14, 2024
5 changes: 5 additions & 0 deletions .changeset/swift-parents-wait.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"penpot-exporter": minor
---

Added support for autolayout
2 changes: 1 addition & 1 deletion plugin-src/findAllTextnodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const findAllTextNodes = async () => {
extractMissingFonts(node, fonts);
}

sleep(0);
await sleep(0);
}
}

Expand Down
1 change: 1 addition & 0 deletions plugin-src/transformers/partials/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from './transformDimensionAndPosition';
export * from './transformEffects';
export * from './transformFigmaIds';
export * from './transformFills';
export * from './transformLayout';
export * from './transformProportion';
export * from './transformRotationAndPosition';
export * from './transformSceneNode';
Expand Down
44 changes: 44 additions & 0 deletions plugin-src/transformers/partials/transformLayout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {
translateLayoutAlignContent,
translateLayoutAlignItems,
translateLayoutFlexDir,
translateLayoutGap,
translateLayoutJustifyContent,
translateLayoutJustifyItems,
translateLayoutPadding,
translateLayoutSizing,
translateLayoutWrapType
} from '@plugin/translators';

import { LayoutAttributes, LayoutChildAttributes } from '@ui/lib/types/shapes/layout';

export const transformAutoLayout = (node: BaseFrameMixin): LayoutAttributes => {
return {
layout: node.layoutMode !== 'NONE' ? 'flex' : undefined,
layoutFlexDir: translateLayoutFlexDir(node.layoutMode),
layoutGap: translateLayoutGap(
node.layoutMode,
node.itemSpacing,
node.primaryAxisAlignItems === 'SPACE_BETWEEN'
),
layoutWrapType: translateLayoutWrapType(node.layoutWrap),
layoutPadding: translateLayoutPadding(node),
layoutJustifyContent: translateLayoutJustifyContent(node),
layoutJustifyItems: translateLayoutJustifyItems(node),
layoutAlignContent: translateLayoutAlignContent(node),
layoutAlignItems: translateLayoutAlignItems(node)
};
};

export const transformLayoutAttributes = (
node: LayoutMixin
): Pick<
LayoutChildAttributes,
'layoutItemH-Sizing' | 'layoutItemV-Sizing' | 'layoutItemAbsolute'
> => {
return {
'layoutItemH-Sizing': translateLayoutSizing(node.layoutSizingHorizontal),
'layoutItemV-Sizing': translateLayoutSizing(node.layoutSizingVertical),
'layoutItemAbsolute': node.layoutPositioning === 'ABSOLUTE'
};
};
4 changes: 3 additions & 1 deletion plugin-src/transformers/partials/transformVectorPaths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
transformBlend,
transformDimensionAndPositionFromVectorPath,
transformEffects,
transformLayoutAttributes,
transformProportion,
transformSceneNode,
transformStrokesFromVector
Expand Down Expand Up @@ -110,6 +111,7 @@ const transformVectorPath = (
...transformDimensionAndPositionFromVectorPath(vectorPath, baseX, baseY),
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node)
...transformProportion(node),
...transformLayoutAttributes(node)
};
};
4 changes: 3 additions & 1 deletion plugin-src/transformers/transformBooleanNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
transformEffects,
transformFigmaIds,
transformFills,
transformLayoutAttributes,
transformProportion,
transformSceneNode,
transformStrokes
Expand All @@ -30,6 +31,7 @@ export const transformBooleanNode = async (
...transformDimensionAndPosition(node, baseX, baseY),
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node)
...transformProportion(node),
...transformLayoutAttributes(node)
};
};
6 changes: 5 additions & 1 deletion plugin-src/transformers/transformComponentNode.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { componentsLibrary } from '@plugin/ComponentLibrary';
import {
transformAutoLayout,
transformBlend,
transformChildren,
transformConstraints,
Expand All @@ -8,6 +9,7 @@ import {
transformEffects,
transformFigmaIds,
transformFills,
transformLayoutAttributes,
transformProportion,
transformSceneNode,
transformStrokes
Expand All @@ -32,10 +34,12 @@ export const transformComponentNode = async (
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node),
...transformLayoutAttributes(node),
...transformCornerRadius(node),
...(await transformChildren(node, baseX + node.x, baseY + node.y)),
...transformDimensionAndPosition(node, baseX, baseY),
...transformConstraints(node)
...transformConstraints(node),
...transformAutoLayout(node)
});

return {
Expand Down
2 changes: 2 additions & 0 deletions plugin-src/transformers/transformEllipseNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
transformEffects,
transformFigmaIds,
transformFills,
transformLayoutAttributes,
transformProportion,
transformRotationAndPosition,
transformSceneNode,
Expand All @@ -30,6 +31,7 @@ export const transformEllipseNode = (
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node),
...transformLayoutAttributes(node),
...transformConstraints(node)
};
};
6 changes: 5 additions & 1 deletion plugin-src/transformers/transformFrameNode.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
transformAutoLayout,
transformBlend,
transformChildren,
transformConstraints,
Expand All @@ -7,6 +8,7 @@ import {
transformEffects,
transformFigmaIds,
transformFills,
transformLayoutAttributes,
transformProportion,
transformSceneNode,
transformStrokes
Expand Down Expand Up @@ -34,9 +36,11 @@ export const transformFrameNode = async (
// @see: https://forum.figma.com/t/add-a-blendmode-property-for-sectionnode/58560
...transformBlend(node),
...transformProportion(node),
...transformLayoutAttributes(node),
...transformCornerRadius(node),
...transformEffects(node),
...transformConstraints(node)
...transformConstraints(node),
...transformAutoLayout(node)
};
}

Expand Down
4 changes: 4 additions & 0 deletions plugin-src/transformers/transformInstanceNode.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { remoteComponentLibrary } from '@plugin/RemoteComponentLibrary';
import {
transformAutoLayout,
transformBlend,
transformChildren,
transformConstraints,
Expand All @@ -8,6 +9,7 @@ import {
transformEffects,
transformFigmaIds,
transformFills,
transformLayoutAttributes,
transformProportion,
transformSceneNode,
transformStrokes
Expand Down Expand Up @@ -43,9 +45,11 @@ export const transformInstanceNode = async (
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node),
...transformLayoutAttributes(node),
...transformCornerRadius(node),
...transformDimensionAndPosition(node, baseX, baseY),
...transformConstraints(node),
...transformAutoLayout(node),
...(await transformChildren(node, baseX + node.x, baseY + node.y))
};
};
Expand Down
2 changes: 2 additions & 0 deletions plugin-src/transformers/transformPathNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
transformEffects,
transformFigmaIds,
transformFills,
transformLayoutAttributes,
transformProportion,
transformSceneNode,
transformStrokes,
Expand Down Expand Up @@ -34,6 +35,7 @@ export const transformPathNode = (
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node),
...transformLayoutAttributes(node),
...transformConstraints(node)
};
};
2 changes: 2 additions & 0 deletions plugin-src/transformers/transformRectangleNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
transformEffects,
transformFigmaIds,
transformFills,
transformLayoutAttributes,
transformProportion,
transformRotationAndPosition,
transformSceneNode,
Expand All @@ -31,6 +32,7 @@ export const transformRectangleNode = (
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node),
...transformLayoutAttributes(node),
...transformCornerRadius(node),
...transformConstraints(node)
};
Expand Down
2 changes: 2 additions & 0 deletions plugin-src/transformers/transformTextNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
transformDimensionAndPosition,
transformEffects,
transformFigmaIds,
transformLayoutAttributes,
transformProportion,
transformSceneNode,
transformStrokes,
Expand All @@ -23,6 +24,7 @@ export const transformTextNode = (node: TextNode, baseX: number, baseY: number):
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node),
...transformLayoutAttributes(node),
...transformStrokes(node),
...transformConstraints(node)
};
Expand Down
1 change: 1 addition & 0 deletions plugin-src/translators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export * from './translateBlurEffects';
export * from './translateBoolType';
export * from './translateChildren';
export * from './translateConstraints';
export * from './translateLayout';
export * from './translateShadowEffects';
export * from './translateStrokes';
127 changes: 127 additions & 0 deletions plugin-src/translators/translateLayout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import {
JustifyAlignContent,
JustifyAlignItems,
LayoutFlexDir,
LayoutGap,
LayoutPadding,
LayoutSizing,
LayoutWrapType
} from '@ui/lib/types/shapes/layout';

type FigmaLayoutMode = 'NONE' | 'HORIZONTAL' | 'VERTICAL';

type FigmaWrap = 'NO_WRAP' | 'WRAP';

type FigmaLayoutSizing = 'FIXED' | 'HUG' | 'FILL';

export const translateLayoutFlexDir = (layoutMode: FigmaLayoutMode): LayoutFlexDir | undefined => {
switch (layoutMode) {
case 'HORIZONTAL':
return 'row-reverse';
case 'VERTICAL':
return 'column-reverse';
default:
return;
}
};

export const translateLayoutGap = (
layoutMode: FigmaLayoutMode,
itemSpacing: number,
auto: boolean = false
): LayoutGap => {
if (auto) {
return {
rowGap: 0,
columnGap: 0
};
}

return {
rowGap: layoutMode === 'VERTICAL' ? itemSpacing : 0,
columnGap: layoutMode === 'HORIZONTAL' ? itemSpacing : 0
};
};

export const translateLayoutWrapType = (wrap: FigmaWrap): LayoutWrapType => {
switch (wrap) {
case 'NO_WRAP':
return 'nowrap';
case 'WRAP':
return 'wrap';
}
};

export const translateLayoutPadding = (node: BaseFrameMixin): LayoutPadding => {
return {
p1: node.paddingTop,
p2: node.paddingRight,
p3: node.paddingBottom,
p4: node.paddingLeft
};
};

export const translateLayoutJustifyContent = (node: BaseFrameMixin): JustifyAlignContent => {
switch (node.primaryAxisAlignItems) {
case 'MIN':
return 'start';
case 'CENTER':
return 'center';
case 'MAX':
return 'end';
case 'SPACE_BETWEEN':
return 'space-between';
default:
return 'stretch';
}
};

export const translateLayoutJustifyItems = (node: BaseFrameMixin): JustifyAlignItems => {
switch (node.primaryAxisAlignItems) {
case 'MIN':
return 'start';
case 'CENTER':
return 'center';
case 'MAX':
return 'end';
default:
return 'stretch';
}
};

export const translateLayoutAlignContent = (node: BaseFrameMixin): JustifyAlignContent => {
switch (node.counterAxisAlignItems) {
case 'MIN':
return 'start';
case 'CENTER':
return 'center';
case 'MAX':
return 'end';
default:
return 'stretch';
}
};

export const translateLayoutAlignItems = (node: BaseFrameMixin): JustifyAlignItems => {
switch (node.counterAxisAlignItems) {
case 'MIN':
return 'start';
case 'CENTER':
return 'center';
case 'MAX':
return 'end';
default:
return 'stretch';
}
};

export const translateLayoutSizing = (sizing: FigmaLayoutSizing): LayoutSizing => {
switch (sizing) {
case 'FIXED':
return 'fix';
case 'HUG':
return 'auto';
case 'FILL':
return 'fill';
}
};
Loading