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

Combinations import done #1

Open
wants to merge 43 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
d5ae4cd
Fix typing issues
AtomicScience Dec 27, 2021
bd88981
Addon renamed properly
AtomicScience Dec 27, 2021
7cd1ea4
Moved global 'enabled' value to constants
AtomicScience Dec 27, 2021
a292bac
Unnecessary debug logging removed
AtomicScience Dec 27, 2021
1ae3188
Proper icon is now used
AtomicScience Dec 27, 2021
79070e4
Unnecessary panel removed
AtomicScience Dec 27, 2021
17537d2
Couple of changes
AtomicScience Jan 10, 2022
ea8ffcb
Tab file structured changed
AtomicScience Jan 10, 2022
c1cd516
Combinations implemented
AtomicScience Jan 11, 2022
9df41d1
Wrappers separated
AtomicScience Jan 12, 2022
e272b89
Edge case for combinations covered
AtomicScience Jan 12, 2022
83bd444
Globals are now properly registered
AtomicScience Jan 14, 2022
b18cb3b
Introduced new hook for working with globals
AtomicScience Jan 14, 2022
cd62bb4
Fixed hook execution in branches
AtomicScience Jan 14, 2022
5b8fd1d
Updates to the package files
AtomicScience Jan 17, 2022
67ceb1e
Hooks for current story and component names added
AtomicScience Jan 19, 2022
7635a37
sendToFigma method now has two variations
AtomicScience Jan 19, 2022
3a367be
Figma window enlarged
AtomicScience Feb 2, 2022
7020314
Combinations implemented
AtomicScience Feb 2, 2022
9bd60bf
useWrapperActive hook added
AtomicScience Feb 2, 2022
e5e9459
Variants import (probably) implemented
AtomicScience Feb 2, 2022
e7906eb
Fixed minor closure-related issue with events
AtomicScience Feb 2, 2022
000bacc
Actually send a message now
AtomicScience Feb 2, 2022
49fb17e
Legacy figma-related code split into separate files
AtomicScience Feb 2, 2022
0169055
Component import now works on plugin
AtomicScience Feb 3, 2022
0f3529e
Output unknown request type
AtomicScience Feb 3, 2022
33fc680
Debug console output removed
AtomicScience Feb 7, 2022
bec6158
Minor changed to CombinePanel
AtomicScience Feb 7, 2022
62e02d3
Rehauled imports in addon
AtomicScience Feb 7, 2022
fe0b2e2
convertElementToSingleLayer function removed
AtomicScience Feb 7, 2022
be71126
objectToPlainObject function simplified
AtomicScience Feb 7, 2022
59f37d0
Awkward code refactored
AtomicScience Feb 7, 2022
c5f0bb4
Minor fixes
AtomicScience Feb 7, 2022
16918b1
Fixed TypeScript errors
AtomicScience Feb 7, 2022
239ccd3
GenerateCombinations function replaced with a more stable one
AtomicScience Feb 7, 2022
3000e88
useWrapperActive renamed
AtomicScience Feb 7, 2022
ca2dc61
setPluginData function removed
AtomicScience Feb 8, 2022
bce2b15
Magic values moved to variables
AtomicScience Feb 8, 2022
240a13f
Unnecessary fragment removed
AtomicScience Feb 8, 2022
f42277d
Commented the generateCombinations + rehauled types
AtomicScience Feb 8, 2022
913688c
FigmaStorage types rehauled
AtomicScience Feb 8, 2022
3e45013
If replaced with ternary
AtomicScience Feb 8, 2022
7c685e8
Unnecessary `any`s replaced with proper types
AtomicScience Feb 8, 2022
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
29 changes: 15 additions & 14 deletions packages/figma-plugin/src/figma.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { defaultFont, getDropOffset, addLayersToFrame } from 'html-figma/figma';
import { FigmaImportMessage, FigmaImportVariantsMessage, FigmaImportVariantsNode, FigmaMessageType } from './modules/FigmaMessageType';
import FigmaRequestListener from './modules/figmaStorage/FigmaRequestListener';
import { importSingle } from './modules/importFunctions/importSingle';
import { importVariants } from './modules/importFunctions/importVariants';

const figmaRequestListener = new FigmaRequestListener(figma);

figma.showUI(__html__, {
width: 750,
height: 600,
width: 1125,
height: 900,
})

figma.ui.onmessage = async (message) => {
Expand All @@ -14,25 +17,23 @@ figma.ui.onmessage = async (message) => {
if(data) {
await processAddonMessage(message)
} else {
await figmaRequestListener.processPossibleRequest(message);
await figmaRequestListener.processPossibleMessage(message);
}
}

async function processAddonMessage(message : any) : Promise<void> {
async function processAddonMessage(message : FigmaImportMessage | FigmaImportVariantsMessage) : Promise<void> {
await figma.loadFontAsync(defaultFont);

let baseFrame: PageNode | FrameNode = figma.currentPage;

const { data } = message;
let { nodes, type } = data;
const { data, type } = message;
let { nodes } = data;

for (const { id, layer, position, componentData } of nodes) {
if (position) {
const { x, y } = getDropOffset(position);
layer.x = x;
layer.y = y;
}

await addLayersToFrame([layer], baseFrame);
if(type === FigmaMessageType.IMPORT) {
AtomicScience marked this conversation as resolved.
Show resolved Hide resolved
importSingle(nodes, baseFrame)
} else if(type === FigmaMessageType.IMPORT_VARIANTS) {
importVariants(nodes as FigmaImportVariantsNode[], baseFrame)
} else {
console.warn("Unknown message type :" + type)
}
}
AtomicScience marked this conversation as resolved.
Show resolved Hide resolved
95 changes: 95 additions & 0 deletions packages/figma-plugin/src/modules/FigmaMessageType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { PlainLayerNode } from 'html-figma/types';

export enum FigmaMessageType {
IMPORT,
UPDATE,
RENDER,
IMPORT_VARIANTS,
APPLY_TOKEN,
APPLY_TOKENS,
SELECT_NODE,
CLEAR_SELECTION,
RENDER_TOKENS_SYNC,
}

type FigmaImportTypes = 'variants' | 'single';

type LayerPosition = {
dropPosition: { clientX: number; clientY: number };
offset: {
x: number;
y: number;
};
windowSize: { width: number; height: number };
};

type FigmaMessageImportPayload = {
nodes: {
layer: PlainLayerNode;
componentData: { name: string; props: unknown };
id?: string;
position?: LayerPosition;
}[];
type: FigmaImportTypes
};
export interface FigmaImportMessage {
type: FigmaMessageType.IMPORT;
data: FigmaMessageImportPayload;
}

export interface FigmaImportVariantsMessage {
type: FigmaMessageType.IMPORT_VARIANTS;
data: {
nodes: FigmaImportVariantsNode[];
};
}

export interface FigmaImportVariantsNode {
layer: PlainLayerNode;
componentData: { name: string; props: any[] };
}

export interface FigmaRenderMessage {
type: FigmaMessageType.RENDER;
data: {
blocks: { figmaId?: string; name: string; props: unknown }[];
position?: LayerPosition;
type: FigmaImportTypes
};
}

export interface FigmaRenderTokenSyncMessage {
type: FigmaMessageType.RENDER_TOKENS_SYNC;
data: Record<string, string>;
}

export interface FigmaApplyAllTokensMessagePayload {
tokens: Record<string, string>;
}

export interface FigmaApplyAllTokensMessage {
type: FigmaMessageType.APPLY_TOKENS;
data: FigmaApplyAllTokensMessagePayload;
}

export interface FigmaClearSelectionMessage {
type: FigmaMessageType.CLEAR_SELECTION;
}

export type FigmaMessages =
| FigmaImportMessage
| FigmaImportVariantsMessage
| FigmaApplyAllTokensMessage
| FigmaRenderMessage
| FigmaRenderTokenSyncMessage;

export type FigmaPluginMessages =
| FigmaClearSelectionMessage;

export interface PluginMessageEvent extends MessageEvent {
data: FigmaMessages;
}

export interface FigmaMessageEvent extends MessageEvent {
data: FigmaPluginMessages;
}
14 changes: 0 additions & 14 deletions packages/figma-plugin/src/modules/figmaStorage/FigmaRequest.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import FigmaRequest from "./FigmaRequest";
import RequestType from "./requestType";
import { FigmaStorageRequest, FigmaStorageSetRequest, FigmaStorageGetRequest } from "./FigmaStorageRequest";
import { RequestType } from "./RequestType";

export default class FigmaRequestListener {
private figma : PluginAPI;
Expand All @@ -8,32 +8,32 @@ export default class FigmaRequestListener {
this.figma = figma;
}

async processPossibleRequest(request : any) {
if (request?.type === undefined) return;
async processPossibleMessage(message : FigmaStorageRequest) {
if (message?.type === undefined) return;

if (request.type === RequestType.GET) {
await this.processGetRequest(request);
} else if(request.type === RequestType.SET) {
await this.processSetRequest(request);
if (message.type === RequestType.GET) {
await this.processGetMessage(message);
} else if (message.type === RequestType.SET) {
await this.processSetMessage(message);
}
}

private async processGetRequest(request: FigmaRequest) {
private async processGetMessage(request: FigmaStorageGetRequest) {
let key = request.payload;

let readResult = await this.figma.clientStorage.getAsync(key);
let readResult = await this.figma.clientStorage.getAsync(key) as unknown;

this.sendResponceForRequest(request, readResult);
}

private async processSetRequest(request: FigmaRequest) {
private async processSetMessage(request: FigmaStorageSetRequest) {
let { key, value } = request.payload;

await this.figma.clientStorage.setAsync(key, value);
this.sendResponceForRequest(request, "OK");
}

private sendResponceForRequest(request: FigmaRequest, result: any) {
private sendResponceForRequest(request: FigmaStorageRequest, result: unknown) {
let responce = {
timestamp: request.timestamp,
result: result,
Expand Down
28 changes: 18 additions & 10 deletions packages/figma-plugin/src/modules/figmaStorage/FigmaStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,42 @@
FigmaStorage provides a WebStorage-like API to save
data to Figma's clientStorage.
*/
import FigmaRequest from "./FigmaRequest";
import RequestType from "./requestType";
import { FigmaStorageGetRequest, FigmaStorageRequest, FigmaStorageSetRequest } from "./FigmaStorageRequest";
import { RequestType } from "./RequestType";

export default class FigmaStorage {
getItem(key : string) : Promise<any | undefined> {
let request = new FigmaRequest(RequestType.GET, key);
getItem(key : string) : Promise<unknown | undefined> {
let request = {
type : RequestType.GET,
timestamp: Date.now(),
payload: key,
} as FigmaStorageGetRequest;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А здесь и ниже точно нужен каст? Тут тайпскрипт без проблем должен типы резолвить


return sendRequestAndExpectResult(request);
}

setItem(key : string, value : any) : Promise<void> {
let request = new FigmaRequest(RequestType.SET, {key, value});
setItem(key : string, value : unknown) : Promise<void> {
let request = {
type: RequestType.SET,
timestamp: Date.now(),
payload: { key, value },
} as FigmaStorageSetRequest;

return sendRequestAndExpectResult(request);
return sendRequestAndExpectResult(request) as Promise<void>;
}
}

async function sendRequestAndExpectResult(request : FigmaRequest) : Promise<any | undefined> {
async function sendRequestAndExpectResult(request: FigmaStorageRequest): Promise<unknown | undefined> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А это по идее можно сделать женериком тогда каст на 26 строчке можно будет убрать

sendRequest(request);

return createPromiseForRequestResult(request)
}

async function sendRequest(request : FigmaRequest) {
async function sendRequest(request: FigmaStorageRequest) {
window.parent.postMessage({ pluginMessage: request }, "https://www.figma.com");
}

function createPromiseForRequestResult(request: FigmaRequest): Promise<any> {
function createPromiseForRequestResult(request: FigmaStorageRequest): Promise<any> {
return new Promise((resolve, reject) => {
window.addEventListener('message', (e) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А тут кажется есть проблема с тем что ивент листенеры не удаляются. Вообще я бы подумал над тем чтоб ивентлистенер создавался только один раз

P.S responce -> response

let responce = e.data.pluginMessage;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { RequestType } from "./RequestType";

type KeyValuePair = { key: string, value: unknown | undefined};

export type FigmaStorageRequest = FigmaStorageSetRequest | FigmaStorageGetRequest

export interface FigmaStorageSetRequest {
type: RequestType.SET,
timestamp: number,
payload: KeyValuePair,
}

export interface FigmaStorageGetRequest {
type: RequestType.GET,
timestamp: number,
payload: string,
}
6 changes: 2 additions & 4 deletions packages/figma-plugin/src/modules/figmaStorage/RequestType.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
enum RequestType {
export enum RequestType {
GET,
SET
}

export default RequestType;
};
13 changes: 13 additions & 0 deletions packages/figma-plugin/src/modules/importFunctions/importSingle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { addLayersToFrame, getDropOffset } from "html-figma/figma";

export const importSingle = async (nodes : any[], baseFrame : PageNode | FrameNode) => {
for (const { id, layer, position, componentData } of nodes) {
if (position) {
const { x, y } = getDropOffset(position);
layer.x = x;
layer.y = y;
}

await addLayersToFrame([layer], baseFrame);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { addLayersToFrame, getDropOffset } from "html-figma/figma";
import { FigmaImportVariantsNode } from "../FigmaMessageType";

export const importVariants = async (nodes: FigmaImportVariantsNode[], baseFrame: PageNode | FrameNode) => {
let addedNodes: SceneNode[] = [];

for(let { layer, componentData } of nodes) {
const componentLayer = {
...layer,
type: "COMPONENT",
} as any;

await addLayersToFrame([componentLayer], baseFrame, ({ node, parent }) => {
if (!parent) {
node.setPluginData('componentData', JSON.stringify(componentData));
addedNodes.push(node);
}
});
}

addCoordinatesToNodes(addedNodes);
figma.combineAsVariants(addedNodes as ComponentNode[], baseFrame);

addedNodes.forEach((node, index) => {
node.name = getVariantNameFromProps(nodes[index].componentData.props as any)
});
}

const addCoordinatesToNodes = (nodes : any[]) => {
const { x, y } = figma.viewport.center;
let failsafeHeight = 100;
let gap = 10;

let offsetTop = 0;
for (let i = 0; i < nodes.length; i++) {
nodes[i].x = x;
nodes[i].y = y + offsetTop;
offsetTop += (nodes[i].height || failsafeHeight) + gap;
}
}
const getVariantNameFromProps = (props: Record<string, string>) => {
return Object.keys(props)
.filter((key) => key !== 'children')
.map((key) => `${key}=${props[key]}`)
.join(', ');
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export default class StorybookStorage {
}

async requestStorybooks() : Promise<void> {
this.storybooks = await this.figmaStorage.getItem("storybooks");
this.selectedId = await this.figmaStorage.getItem("selectedId");
this.storybooks = await this.figmaStorage.getItem("storybooks") as Storybook[];
this.selectedId = await this.figmaStorage.getItem("selectedId") as string;
Comment on lines +21 to +22
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

По идее тут тоже можно сделать дженерик чтоб не кастить, как по мне так красивее

}

awaitForRequest() {
Expand Down
2 changes: 0 additions & 2 deletions packages/figma-plugin/src/modules/ui/Iframe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ export default class Iframe {
}

private setPlaceholderActive(active : boolean) {
console.log(active);

document.getElementById("iframe_placeholder").style.display = active ? "flex" : "none";
document.getElementById("storybook_iframe").style.display = active ? "none" : "inline";
}
Expand Down
Loading