From 5d4ace337be418b2f4f62d88824a099be8c22b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20S=C3=A1nchez?= Date: Wed, 29 May 2024 17:33:29 +0200 Subject: [PATCH] Components Library (#125) * components library management * components library management * fixes * fixes --- plugin-src/ComponentLibrary.ts | 23 +++++++++++ .../transformers/transformComponentNode.ts | 14 +++++-- .../transformers/transformDocumentNode.ts | 7 +++- plugin-src/transformers/transformSceneNode.ts | 2 +- plugin-src/translators/translateChildren.ts | 2 +- ui-src/components/PenpotExporter.tsx | 2 +- ui-src/lib/types/penpotDocument.ts | 6 --- ui-src/lib/types/utils/children.ts | 2 +- ui-src/parser/creators/createComponent.ts | 38 +++++++++---------- .../parser/creators/createComponentLibrary.ts | 25 ++++++++++-- ui-src/parser/creators/createItems.ts | 2 +- ui-src/parser/libraries/Components.ts | 19 ---------- ui-src/parser/libraries/UiComponents.ts | 30 +++++++++++++++ ui-src/parser/libraries/index.ts | 2 +- ui-src/parser/parse.ts | 15 +++++--- ui-src/types/componentRoot.ts | 4 ++ ui-src/types/index.ts | 3 ++ ui-src/types/penpotDocument.ts | 8 ++++ ui-src/{lib => }/types/penpotNode.ts | 4 +- 19 files changed, 138 insertions(+), 70 deletions(-) create mode 100644 plugin-src/ComponentLibrary.ts delete mode 100644 ui-src/lib/types/penpotDocument.ts delete mode 100644 ui-src/parser/libraries/Components.ts create mode 100644 ui-src/parser/libraries/UiComponents.ts create mode 100644 ui-src/types/componentRoot.ts create mode 100644 ui-src/types/index.ts create mode 100644 ui-src/types/penpotDocument.ts rename ui-src/{lib => }/types/penpotNode.ts (86%) diff --git a/plugin-src/ComponentLibrary.ts b/plugin-src/ComponentLibrary.ts new file mode 100644 index 0000000..7caf425 --- /dev/null +++ b/plugin-src/ComponentLibrary.ts @@ -0,0 +1,23 @@ +import { ComponentShape } from '@ui/lib/types/shapes/componentShape'; + +class ComponentLibrary { + private components: Record = {}; + + public register(id: string, component: ComponentShape) { + this.components[id] = component; + } + + public get(id: string): ComponentShape | undefined { + return this.components[id]; + } + + public all(): Record { + return this.components; + } + + public init(components: Record): void { + this.components = components; + } +} + +export const componentsLibrary = new ComponentLibrary(); diff --git a/plugin-src/transformers/transformComponentNode.ts b/plugin-src/transformers/transformComponentNode.ts index f077bb4..b20f2e9 100644 --- a/plugin-src/transformers/transformComponentNode.ts +++ b/plugin-src/transformers/transformComponentNode.ts @@ -1,5 +1,7 @@ +import { componentsLibrary } from '@plugin/ComponentLibrary'; import { transformBlend, + transformChildren, transformCornerRadius, transformDimensionAndPosition, transformEffects, @@ -8,16 +10,15 @@ import { transformSceneNode, transformStrokes } from '@plugin/transformers/partials'; -import { transformChildren } from '@plugin/transformers/partials'; -import { ComponentShape } from '@ui/lib/types/shapes/componentShape'; +import { ComponentRoot } from '@ui/types'; export const transformComponentNode = async ( node: ComponentNode, baseX: number, baseY: number -): Promise => { - return { +): Promise => { + componentsLibrary.register(node.id, { type: 'component', name: node.name, path: '', @@ -30,5 +31,10 @@ export const transformComponentNode = async ( ...transformCornerRadius(node), ...(await transformChildren(node, baseX + node.x, baseY + node.y)), ...transformDimensionAndPosition(node, baseX, baseY) + }); + + return { + figmaId: node.id, + type: 'component' }; }; diff --git a/plugin-src/transformers/transformDocumentNode.ts b/plugin-src/transformers/transformDocumentNode.ts index 60c7997..784572f 100644 --- a/plugin-src/transformers/transformDocumentNode.ts +++ b/plugin-src/transformers/transformDocumentNode.ts @@ -1,10 +1,13 @@ -import { PenpotDocument } from '@ui/lib/types/penpotDocument'; +import { componentsLibrary } from '@plugin/ComponentLibrary'; + +import { PenpotDocument } from '@ui/types'; import { transformPageNode } from '.'; export const transformDocumentNode = async (node: DocumentNode): Promise => { return { name: node.name, - children: await Promise.all(node.children.map(child => transformPageNode(child))) + children: await Promise.all(node.children.map(child => transformPageNode(child))), + components: componentsLibrary.all() }; }; diff --git a/plugin-src/transformers/transformSceneNode.ts b/plugin-src/transformers/transformSceneNode.ts index be13fc6..e18a08c 100644 --- a/plugin-src/transformers/transformSceneNode.ts +++ b/plugin-src/transformers/transformSceneNode.ts @@ -1,4 +1,4 @@ -import { PenpotNode } from '@ui/lib/types/penpotNode'; +import { PenpotNode } from '@ui/types'; import { transformBooleanNode, diff --git a/plugin-src/translators/translateChildren.ts b/plugin-src/translators/translateChildren.ts index 4d75b0c..5e0c250 100644 --- a/plugin-src/translators/translateChildren.ts +++ b/plugin-src/translators/translateChildren.ts @@ -1,6 +1,6 @@ import { transformGroupNodeLike, transformSceneNode } from '@plugin/transformers'; -import { PenpotNode } from '@ui/lib/types/penpotNode'; +import { PenpotNode } from '@ui/types'; /** * Translates the children of a node that acts as a mask. diff --git a/ui-src/components/PenpotExporter.tsx b/ui-src/components/PenpotExporter.tsx index cbd63c1..a794b68 100644 --- a/ui-src/components/PenpotExporter.tsx +++ b/ui-src/components/PenpotExporter.tsx @@ -3,8 +3,8 @@ import { useEffect, useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { Stack } from '@ui/components/Stack'; -import { PenpotDocument } from '@ui/lib/types/penpotDocument'; import { parse } from '@ui/parser'; +import { PenpotDocument } from '@ui/types'; import { MissingFontsSection } from './MissingFontsSection'; diff --git a/ui-src/lib/types/penpotDocument.ts b/ui-src/lib/types/penpotDocument.ts deleted file mode 100644 index bb53908..0000000 --- a/ui-src/lib/types/penpotDocument.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { PenpotPage } from './penpotPage'; - -export type PenpotDocument = { - name: string; - children?: PenpotPage[]; -}; diff --git a/ui-src/lib/types/utils/children.ts b/ui-src/lib/types/utils/children.ts index 7965a14..d39f696 100644 --- a/ui-src/lib/types/utils/children.ts +++ b/ui-src/lib/types/utils/children.ts @@ -1,3 +1,3 @@ -import { PenpotNode } from '@ui/lib/types/penpotNode'; +import { PenpotNode } from '@ui/types'; export type Children = { children?: PenpotNode[] }; diff --git a/ui-src/parser/creators/createComponent.ts b/ui-src/parser/creators/createComponent.ts index 53c6d16..a2c1179 100644 --- a/ui-src/parser/creators/createComponent.ts +++ b/ui-src/parser/creators/createComponent.ts @@ -1,38 +1,34 @@ +import { componentsLibrary } from '@plugin/ComponentLibrary'; + import { PenpotFile } from '@ui/lib/types/penpotFile'; -import { ComponentShape } from '@ui/lib/types/shapes/componentShape'; -import { components } from '@ui/parser/libraries'; +import { uiComponents } from '@ui/parser/libraries'; +import { ComponentRoot } from '@ui/types'; import { createArtboard } from '.'; -export const createComponent = ( - file: PenpotFile, - { type, path, children = [], ...rest }: ComponentShape -) => { +export const createComponent = (file: PenpotFile, { figmaId }: ComponentRoot) => { const frameId = file.newId(); const componentId = file.newId(); - const commonStructure = { - ...rest, - children, + const component = componentsLibrary.get(figmaId); + if (!component) { + return; + } + + createArtboard(file, { + ...component, componentFile: file.getId(), componentId: componentId, componentRoot: true, - mainInstance: true - }; - - createArtboard(file, { - ...commonStructure, - id: frameId, mainInstance: true, + id: frameId, type: 'frame' }); - components.add({ - ...commonStructure, - id: componentId, - mainInstanceId: frameId, + uiComponents.register(figmaId, { + componentId, mainInstancePage: file.getCurrentPageId(), - path, - type + componentFigmaId: figmaId, + mainInstanceId: frameId }); }; diff --git a/ui-src/parser/creators/createComponentLibrary.ts b/ui-src/parser/creators/createComponentLibrary.ts index e4e0f87..0df1a09 100644 --- a/ui-src/parser/creators/createComponentLibrary.ts +++ b/ui-src/parser/creators/createComponentLibrary.ts @@ -1,12 +1,29 @@ +import { componentsLibrary } from '@plugin/ComponentLibrary'; + import { PenpotFile } from '@ui/lib/types/penpotFile'; -import { ComponentShape } from '@ui/lib/types/shapes/componentShape'; -import { components } from '@ui/parser/libraries'; +import { uiComponents } from '@ui/parser/libraries'; import { createItems } from '.'; export const createComponentLibrary = (file: PenpotFile) => { - components.get().forEach(({ children = [], ...rest }: ComponentShape) => { - file.startComponent(rest); + uiComponents.all().forEach(uiComponent => { + const component = componentsLibrary.get(uiComponent.componentFigmaId); + if (!component) { + return; + } + + const { children = [], ...rest } = component; + + file.startComponent({ + ...rest, + id: uiComponent.componentId, + componentId: uiComponent.componentId, + mainInstancePage: uiComponent.mainInstancePage, + mainInstanceId: uiComponent.mainInstanceId, + componentRoot: true, + mainInstance: true, + componentFile: file.getId() + }); createItems(file, children); diff --git a/ui-src/parser/creators/createItems.ts b/ui-src/parser/creators/createItems.ts index 60c3ad1..e257f58 100644 --- a/ui-src/parser/creators/createItems.ts +++ b/ui-src/parser/creators/createItems.ts @@ -1,5 +1,5 @@ import { PenpotFile } from '@ui/lib/types/penpotFile'; -import { PenpotNode } from '@ui/lib/types/penpotNode'; +import { PenpotNode } from '@ui/types'; import { createArtboard, diff --git a/ui-src/parser/libraries/Components.ts b/ui-src/parser/libraries/Components.ts deleted file mode 100644 index c060b53..0000000 --- a/ui-src/parser/libraries/Components.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ComponentShape } from '@ui/lib/types/shapes/componentShape'; - -class Components { - private components: ComponentShape[] = []; - - public add(component: ComponentShape) { - this.components.push(component); - } - - public get() { - return this.components; - } - - public clear() { - this.components = []; - } -} - -export const components = new Components(); diff --git a/ui-src/parser/libraries/UiComponents.ts b/ui-src/parser/libraries/UiComponents.ts new file mode 100644 index 0000000..358cd7a --- /dev/null +++ b/ui-src/parser/libraries/UiComponents.ts @@ -0,0 +1,30 @@ +import { Uuid } from '@ui/lib/types/utils/uuid'; + +type UiComponent = { + componentId: Uuid; + mainInstancePage: Uuid; + mainInstanceId: Uuid; + componentFigmaId: string; +}; + +class UiComponents { + private components: Record = {}; + + public register(id: string, component: UiComponent) { + this.components[id] = component; + } + + public get(id: string): UiComponent | undefined { + return this.components[id]; + } + + public all(): UiComponent[] { + return Object.values(this.components); + } + + public init() { + this.components = {}; + } +} + +export const uiComponents = new UiComponents(); diff --git a/ui-src/parser/libraries/index.ts b/ui-src/parser/libraries/index.ts index 18fedba..69657ca 100644 --- a/ui-src/parser/libraries/index.ts +++ b/ui-src/parser/libraries/index.ts @@ -1 +1 @@ -export * from './Components'; +export * from './UiComponents'; diff --git a/ui-src/parser/parse.ts b/ui-src/parser/parse.ts index 94fbf53..8becd82 100644 --- a/ui-src/parser/parse.ts +++ b/ui-src/parser/parse.ts @@ -1,10 +1,13 @@ -import { createFile } from '@ui/lib/penpot'; -import { PenpotDocument } from '@ui/lib/types/penpotDocument'; -import { createComponentLibrary, createPage } from '@ui/parser/creators'; -import { components } from '@ui/parser/libraries'; +import { componentsLibrary } from '@plugin/ComponentLibrary'; -export const parse = ({ name, children = [] }: PenpotDocument) => { - components.clear(); +import { createFile } from '@ui/lib/penpot'; +import { createComponentLibrary, createPage } from '@ui/parser/creators'; +import { uiComponents } from '@ui/parser/libraries/UiComponents'; +import { PenpotDocument } from '@ui/types'; + +export const parse = ({ name, children = [], components }: PenpotDocument) => { + componentsLibrary.init(components); + uiComponents.init(); const file = createFile(name); diff --git a/ui-src/types/componentRoot.ts b/ui-src/types/componentRoot.ts new file mode 100644 index 0000000..4036e9a --- /dev/null +++ b/ui-src/types/componentRoot.ts @@ -0,0 +1,4 @@ +export type ComponentRoot = { + figmaId: string; + type: 'component'; +}; diff --git a/ui-src/types/index.ts b/ui-src/types/index.ts new file mode 100644 index 0000000..3eb2105 --- /dev/null +++ b/ui-src/types/index.ts @@ -0,0 +1,3 @@ +export * from './componentRoot'; +export * from './penpotDocument'; +export * from './penpotNode'; diff --git a/ui-src/types/penpotDocument.ts b/ui-src/types/penpotDocument.ts new file mode 100644 index 0000000..9f8b8b0 --- /dev/null +++ b/ui-src/types/penpotDocument.ts @@ -0,0 +1,8 @@ +import { PenpotPage } from '@ui/lib/types/penpotPage'; +import { ComponentShape } from '@ui/lib/types/shapes/componentShape'; + +export type PenpotDocument = { + name: string; + children?: PenpotPage[]; + components: Record; +}; diff --git a/ui-src/lib/types/penpotNode.ts b/ui-src/types/penpotNode.ts similarity index 86% rename from ui-src/lib/types/penpotNode.ts rename to ui-src/types/penpotNode.ts index b4f9397..e5d52a5 100644 --- a/ui-src/lib/types/penpotNode.ts +++ b/ui-src/types/penpotNode.ts @@ -1,11 +1,11 @@ import { BoolShape } from '@ui/lib/types/shapes/boolShape'; import { CircleShape } from '@ui/lib/types/shapes/circleShape'; -import { ComponentShape } from '@ui/lib/types/shapes/componentShape'; import { FrameShape } from '@ui/lib/types/shapes/frameShape'; import { GroupShape } from '@ui/lib/types/shapes/groupShape'; import { PathShape } from '@ui/lib/types/shapes/pathShape'; import { RectShape } from '@ui/lib/types/shapes/rectShape'; import { TextShape } from '@ui/lib/types/shapes/textShape'; +import { ComponentRoot } from '@ui/types'; export type PenpotNode = | FrameShape @@ -15,4 +15,4 @@ export type PenpotNode = | CircleShape | TextShape | BoolShape - | ComponentShape; + | ComponentRoot;