Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 87 additions & 16 deletions packages/adaptive-ui-designer-figma-plugin/src/figma/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,26 @@ function isShapeNode(node: BaseNode): node is
].some((test: (node: BaseNode) => boolean) => test(node));
}

function canHaveIndividualStrokes(node: BaseNode): node is
FrameNode |
ComponentNode |
InstanceNode |
RectangleNode {
return [
isContainerNode,
isRectangleNode,
].some((test: (node: BaseNode) => boolean) => test(node));
}

function canHaveChildren(node: BaseNode): node is
| DocumentNode
| PageNode
| FrameNode
| GroupNode
| BooleanOperationNode
| InstanceNode
| ComponentNode
| ComponentSetNode {
DocumentNode |
PageNode |
FrameNode |
GroupNode |
BooleanOperationNode |
InstanceNode |
ComponentNode |
ComponentSetNode {
return [
isDocumentNode,
isPageNode,
Expand Down Expand Up @@ -391,7 +402,7 @@ export class FigmaPluginNode extends PluginNode {
case StyleProperty.gap:
return [
isContainerNode,
].some((test: (node: BaseNode) => boolean) => test(this._node));
].some((test: (node: BaseNode) => boolean) => test(this._node));
case StyleProperty.cornerRadiusTopLeft:
case StyleProperty.cornerRadiusTopRight:
case StyleProperty.cornerRadiusBottomRight:
Expand Down Expand Up @@ -510,7 +521,7 @@ export class FigmaPluginNode extends PluginNode {
}

protected handleFontFamily(node: FigmaPluginNode, values: AppliedStyleValues) {
const fontFamily = values?.get(StyleProperty.fontFamily)?.value;
const fontFamily = values.get(StyleProperty.fontFamily)?.value;
// We'll only set the font if the family is provided.
if (fontFamily) {
if (isTextNode(node._node)) {
Expand Down Expand Up @@ -541,6 +552,38 @@ export class FigmaPluginNode extends PluginNode {
}
}

/**
* Cleans up stroke values based on what we're about to apply.
*
* @remarks
* Figma has a default invisible stroke width of `1`. If you add a stroke in the UI
* it sets the weight to `1` and adds a default color.
* If you change the weight, then remove the strokes (nothing visible) it maintains
* the old stroke weight, but when you add again it resets to `1`.
*
* @param values - The entire list of values to be applied
*/
private handleStroke(values: AppliedStyleValues) {
const applyingFill = values.has(StyleProperty.borderFillTop)
|| values.has(StyleProperty.borderFillRight)
|| values.has(StyleProperty.borderFillBottom)
|| values.has(StyleProperty.borderFillLeft);
const applyingThickness = values.has(StyleProperty.borderThicknessTop)
|| values.has(StyleProperty.borderThicknessRight)
|| values.has(StyleProperty.borderThicknessBottom)
|| values.has(StyleProperty.borderThicknessLeft);

if (applyingFill && applyingThickness) {
// We only need to reset "individual" strokes here since we'll set a common stroke later anyway.
if (canHaveIndividualStrokes(this._node)) {
(this._node as IndividualStrokesMixin).strokeTopWeight = 0;
(this._node as IndividualStrokesMixin).strokeRightWeight = 0;
(this._node as IndividualStrokesMixin).strokeBottomWeight = 0;
(this._node as IndividualStrokesMixin).strokeLeftWeight = 0;
}
}
}

protected safeNumber(value: string, defaultValue: number = 0) {
return value === STYLE_REMOVE ? defaultValue : Number.parseFloat(value);
}
Expand All @@ -549,6 +592,8 @@ export class FigmaPluginNode extends PluginNode {
// Fonts are complicated in Figma, so pull them out of the normal loop.
this.handleFontFamily(this, values);

this.handleStroke(values);

// Paint all applied design tokens on the node
values.forEach((styleValue, target) => {
// console.log("applied design token eval", target, applied);
Expand Down Expand Up @@ -591,7 +636,7 @@ export class FigmaPluginNode extends PluginNode {
case StyleProperty.borderThicknessBottom:
case StyleProperty.borderThicknessLeft:
this.setBoxSizing();
this.paintStrokeWidth(value);
this.paintStrokeWidth(target, value);
break;
case StyleProperty.cornerRadiusTopLeft:
case StyleProperty.cornerRadiusTopRight:
Expand Down Expand Up @@ -879,16 +924,42 @@ export class FigmaPluginNode extends PluginNode {
(this._node as MinimalFillsMixin).fills = paint ? [paint] : [SOLID_BLACK];
break;
case StyleProperty.borderFillTop:
case StyleProperty.borderFillRight:
case StyleProperty.borderFillBottom:
case StyleProperty.borderFillLeft:
// TODO: Figma only supports one border color, though it can be hacked using inner shadow.
(this._node as MinimalStrokesMixin).strokes = paintValue;
break;
}
}

private paintStrokeWidth(value: string): void {
(this._node as MinimalStrokesMixin).strokeWeight = this.safeNumber(value);
if ((this._node as MinimalStrokesMixin).strokes.length === 0) {
(this._node as MinimalStrokesMixin).strokes = [SOLID_TRANSPARENT];
private paintStrokeWidth(target: StyleProperty, value: string): void {
try {
const numValue = this.safeNumber(value);
if (canHaveIndividualStrokes(this._node)) {
switch (target) {
case StyleProperty.borderThicknessTop:
(this._node as IndividualStrokesMixin).strokeTopWeight = numValue;
break;
case StyleProperty.borderThicknessRight:
(this._node as IndividualStrokesMixin).strokeRightWeight = numValue;
break;
case StyleProperty.borderThicknessBottom:
(this._node as IndividualStrokesMixin).strokeBottomWeight = numValue;
break;
case StyleProperty.borderThicknessLeft:
(this._node as IndividualStrokesMixin).strokeLeftWeight = numValue;
break;
}
} else {
(this._node as MinimalStrokesMixin).strokeWeight = this.safeNumber(value);
}

if ((this._node as MinimalStrokesMixin).strokes.length === 0) {
(this._node as MinimalStrokesMixin).strokes = [SOLID_TRANSPARENT];
}
} catch (error) {
console.error("paintStrokeWidth", { target, value, error, ...this.debugInfo });
}
}

Expand Down Expand Up @@ -1010,7 +1081,7 @@ export class FigmaPluginNode extends PluginNode {
}]
}];

y += restComponent.height + spacing;
y += restComponent.height + spacing;
});

this._node.resize(x - spacing + paddingRight, y - spacing + paddingBottom);
Expand Down