From 1860384a33ac8c30f2342f586a48a382d461e8eb Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Tue, 28 Dec 2021 23:05:49 +0900 Subject: [PATCH 01/12] update component property reading --- externals/design-sdk | 2 +- packages/support-components/define.ts | 112 ++++++++++++------ packages/support-components/main.ts | 11 +- .../tokens/token-master-component.ts | 10 +- 4 files changed, 86 insertions(+), 49 deletions(-) diff --git a/externals/design-sdk b/externals/design-sdk index 34a45ef2..6e2e8b0c 160000 --- a/externals/design-sdk +++ b/externals/design-sdk @@ -1 +1 @@ -Subproject commit 34a45ef238a9fbc635cfdf5f66baab77c7a0cab9 +Subproject commit 6e2e8b0cebad3f5808c72864e897969e50f919d3 diff --git a/packages/support-components/define.ts b/packages/support-components/define.ts index b0cf4d9e..bcbe3fdc 100644 --- a/packages/support-components/define.ts +++ b/packages/support-components/define.ts @@ -1,11 +1,14 @@ import { Figma, ReflectSceneNode } from "@design-sdk/figma"; import { compare_instance_with_master, - InstanceDiff, + InstanceDiff_1on1, NodeDiff, } from "@design-sdk/diff"; import { ComponentsUsageRepository } from "./components-usage-repository"; -import { MasterComponentMetaToken } from "./tokens/token-master-component"; +import { + MasterComponentMetaToken, + Property, +} from "./tokens/token-master-component"; import { InstanceMetaToken } from "./tokens/token-instance"; import { keyFromNode } from "@designto/token/key"; @@ -35,53 +38,79 @@ interface Input { references?: Figma.InstanceNode[]; } -interface Definition { +/** + * A single property definition + */ +interface PropertyDefinition { type: string; + /** + * id of the master + */ master: string; + /** + * id of the instance + */ use: string; + /** + * default value from master + */ default_value: string; + /** + * overrided value from instance + */ overrided_value: string; } +/** + * defines properties as array of PropertyDefinition from whole diff data between master/instance + * @param diff + * @returns + */ +function define_props(diff: NodeDiff): PropertyDefinition[] { + if (!diff.diff) return; + const masterId = diff.ids[0]; + const instanceId = diff.ids[1]; + console.log("diff.type", diff.type); + switch (diff.type) { + case "instance-to-master": + throw "instance-to-master - not implemented"; // TODO: + return define_props__instance(diff as any) as any; + break; + case "text-node": + return [ + diff.characters.diff + ? { + type: "text.data", + default_value: diff.characters.values[0], + overrided_value: diff.characters.values[1], + master: masterId, + use: instanceId, + } + : null, + // TODO: add text styles diff support + ]; + break; + } +} + +const define_props__instance = (diff: InstanceDiff_1on1) => { + return diff.values + .map((d) => { + return define_props(d); + }) + .flat() + .filter((d) => d); // remove nulls +}; + export function make_instance_component_meta({ entry, components }: Input) { const property_meta = overrided_property_meta({ entry, components }); - const define = (diff: NodeDiff): Definition[] | Definition[][] => { - if (diff.diff) { - const master = diff.ids[0]; - const use = diff.ids[1]; - switch (diff.type) { - case "instance-to-master": - return define_instance(diff); - case "text-node": - return [ - diff.characters.diff - ? { - type: "text.data", - default_value: diff.characters.values[0], - overrided_value: diff.characters.values[1], - master: master, - use: use, - } - : null, - ]; - break; - } - } - }; - const define_instance = (diff: InstanceDiff) => { - const definitions = diff.values.map((d) => { - return define(d); - }); - return definitions.filter((d) => d) as any; - }; - - const properties = define_instance(property_meta); + const properties = define_props__instance(property_meta).flat(); const master = new MasterComponentMetaToken({ key: keyFromNode(findIn(components, property_meta.ids[0])), properties: properties.map((p) => { - return { + return >{ key: p.type, type: p.type, defaultValue: p.default_value, @@ -89,8 +118,8 @@ export function make_instance_component_meta({ entry, components }: Input) { type: "design-link", linksto: { type: "path-property-link", - path: "", - property: p.type, + path: p.type, + property: [{ type: "name", value: p.type }], }, // TODO: }, }; @@ -120,12 +149,19 @@ function overrided_property_meta({ entry, components }: Input) { if ( // TODO: needs cleanup "origin" in entry - ? ((entry as any) as ReflectSceneNode).origin !== "INSTANCE" + ? (entry as any as ReflectSceneNode).origin !== "INSTANCE" : entry.type !== "INSTANCE" ) { throw new Error("not a instance"); } const _master = findIn(components, entry.mainComponentId); + if (!_master) + throw new Error( + "cannot find master with `mainComponentId` - id " + + entry.mainComponentId + + `\nIn map provided - length of ${components.length}` + ); + const diff = compare_instance_with_master({ instance: entry, master: _master, diff --git a/packages/support-components/main.ts b/packages/support-components/main.ts index 14db3876..cc6f363c 100644 --- a/packages/support-components/main.ts +++ b/packages/support-components/main.ts @@ -28,6 +28,7 @@ export function reusable({ */ entry: RenderObjectWidget; }): ReusableWidgetResult { + console.log("repository", repository); // all instances in the input scope const instances = repository.nodes.filter( (node) => node.origin === "INSTANCE" @@ -37,9 +38,8 @@ export function reusable({ components: repository.components, }); - const components = component_use_repository.components.map( - composeComponentMeta - ); + const components = + component_use_repository.components.map(composeComponentMeta); return { // asumming root is always a multi child widget @@ -106,9 +106,8 @@ function composeComponentMeta( component: MasterComponentMetaToken ): MasterComponentWidget { const componentNode = component.body as ComponentNode; - const componentTokenizedBody = tokenizeComponent.fromComponentNode( - componentNode - ); + const componentTokenizedBody = + tokenizeComponent.fromComponentNode(componentNode); return new MasterComponentWidget({ key: component.key, diff --git a/packages/support-components/tokens/token-master-component.ts b/packages/support-components/tokens/token-master-component.ts index 950ea86b..7889cd74 100644 --- a/packages/support-components/tokens/token-master-component.ts +++ b/packages/support-components/tokens/token-master-component.ts @@ -46,25 +46,27 @@ export class MasterComponentMetaToken { } } -interface Property { +export interface Property { key: string; type: any; defaultValue: any; link: PropertyLink; } -type PropertyLink = InstanciationPropertyLink | DesignPropertyLink; +export type PropertyLink = + | InstanciationPropertyLink + | DesignPropertyLink; /** * Property link to a instanciation of (another) component. */ -interface InstanciationPropertyLink { +export interface InstanciationPropertyLink { type: "instanciation-link"; master: MasterComponentMetaToken; linksto: Link; } -interface DesignPropertyLink { +export interface DesignPropertyLink { type: "design-link"; /** * path to a property as indexpath. From 9e3f41497ee3e317a0a18d9b07f5a43a1bfe429f Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Tue, 28 Dec 2021 23:06:27 +0900 Subject: [PATCH 02/12] add components to editor state for always-reference --- editor/core/states/editor-state.ts | 5 +- editor/core/states/workspace-initial-state.ts | 7 +- .../workspace-bottom-panel-dock-layout.tsx | 2 - editor/pages/figma/inspect-component.tsx | 12 +- editor/pages/files/[key]/[id].tsx | 12 +- editor/pages/files/[key]/index.tsx | 20 ++-- editor/pages/to-code/index.tsx | 12 +- editor/scaffolds/editor/editor.tsx | 108 +++++++++++------- editor/scaffolds/editor/warmup.ts | 62 ++++++++++ packages/builder-config/input/design-input.ts | 37 ++++-- 10 files changed, 180 insertions(+), 97 deletions(-) diff --git a/editor/core/states/editor-state.ts b/editor/core/states/editor-state.ts index e0441504..7d80175e 100644 --- a/editor/core/states/editor-state.ts +++ b/editor/core/states/editor-state.ts @@ -1,4 +1,5 @@ import type { ReflectSceneNode } from "@design-sdk/figma-node"; +import { ComponentNode } from "@design-sdk/figma-types"; import { DesignInput } from "@designto/config/input"; export interface EditorState { @@ -15,7 +16,7 @@ export interface EditorSnapshot { design: FigmaReflectRepository; } -interface FigmaReflectRepository { +export interface FigmaReflectRepository { /** * fileid; filekey */ @@ -23,5 +24,7 @@ interface FigmaReflectRepository { // TODO: pages: { id: string; name: string; children: ReflectSceneNode[] }[]; + components: { [key: string]: ComponentNode }; + // styles: { [key: string]: {} }; input: DesignInput; } diff --git a/editor/core/states/workspace-initial-state.ts b/editor/core/states/workspace-initial-state.ts index a54976be..59c9828d 100644 --- a/editor/core/states/workspace-initial-state.ts +++ b/editor/core/states/workspace-initial-state.ts @@ -12,8 +12,9 @@ export function createInitialWorkspaceState( return { history: createInitialHistoryState(editor), preferences: { - debug_mode: false, - enable_preview_feature_components_support: false, + // TODO: temporarily always true for components dev + debug_mode: true, + enable_preview_feature_components_support: true, preview_runner_framework_config: vanilla_presets.vanilla_default, framework_config: react_presets.react_default, }, @@ -25,7 +26,7 @@ export function createPendingWorkspaceState(): WorkspaceState { history: createPendingHistoryState(), preferences: { debug_mode: false, - enable_preview_feature_components_support: false, + enable_preview_feature_components_support: true, preview_runner_framework_config: null, framework_config: null, }, diff --git a/editor/layouts/panel/workspace-bottom-panel-dock-layout.tsx b/editor/layouts/panel/workspace-bottom-panel-dock-layout.tsx index 7c1e53d6..989924ee 100644 --- a/editor/layouts/panel/workspace-bottom-panel-dock-layout.tsx +++ b/editor/layouts/panel/workspace-bottom-panel-dock-layout.tsx @@ -40,9 +40,7 @@ export function WorkspaceBottomPanelDockLayout(props: { } const DockRootWrap = styled.div` - border: solid #d2d2d2; align-self: stretch; - border-width: 1px; display: flex; flex-direction: row; `; diff --git a/editor/pages/figma/inspect-component.tsx b/editor/pages/figma/inspect-component.tsx index fe5ea97e..b32be44f 100644 --- a/editor/pages/figma/inspect-component.tsx +++ b/editor/pages/figma/inspect-component.tsx @@ -87,26 +87,22 @@ export default function InspectComponent() { -
+ {/*
-
-
+
*/} + {/*
-
+
*/}
- {/*
- - -
*/} {/*
diff --git a/editor/pages/files/[key]/[id].tsx b/editor/pages/files/[key]/[id].tsx index e83d17c2..39bc740b 100644 --- a/editor/pages/files/[key]/[id].tsx +++ b/editor/pages/files/[key]/[id].tsx @@ -56,15 +56,8 @@ export default function Page() { if (file) { let val: EditorSnapshot; - const pages = file.document.children.map((page) => ({ - id: page.id, - name: page.name, - children: page["children"]?.map((child) => { - const _mapped = mapper.mapFigmaRemoteToFigma(child); - return convert.intoReflectNode(_mapped); - }), - type: "design", - })); + const components = warmup.componentsFrom(file); + const pages = warmup.pagesFrom(file); if (prevstate) { val = { @@ -102,6 +95,7 @@ export default function Page() { input: null, key: filekey, pages: pages, + components: components, }, selectedPage: warmup.selectedPage(prevstate, pages, null), }; diff --git a/editor/pages/files/[key]/index.tsx b/editor/pages/files/[key]/index.tsx index 4e599068..93312fc6 100644 --- a/editor/pages/files/[key]/index.tsx +++ b/editor/pages/files/[key]/index.tsx @@ -5,8 +5,7 @@ import { Editor } from "scaffolds/editor"; import { EditorSnapshot, StateProvider } from "core/states"; import { WorkspaceAction } from "core/actions"; import { useDesignFile } from "hooks"; -import { convert } from "@design-sdk/figma-node-conversion"; -import { mapper } from "@design-sdk/figma-remote"; + import { warmup } from "scaffolds/editor"; export default function FileEntryEditor() { @@ -31,15 +30,11 @@ export default function FileEntryEditor() { if (file) { let val: EditorSnapshot; - const pages = file.document.children.map((page) => ({ - id: page.id, - name: page.name, - children: page["children"]?.map((child) => { - const _mapped = mapper.mapFigmaRemoteToFigma(child); - return convert.intoReflectNode(_mapped); - }), - type: "design", - })); + // TODO: seed this as well + // ->> file.styles; + + const components = warmup.componentsFrom(file); + const pages = warmup.pagesFrom(file); if (prevstate) { val = { @@ -60,6 +55,8 @@ export default function FileEntryEditor() { selectedLayersOnPreview: [], design: { input: null, + components: components, + // styles: null, key: filekey, pages: pages, }, @@ -75,7 +72,6 @@ export default function FileEntryEditor() { }, [filekey, file?.document?.children]); const safe_value = warmup.safestate(initialState); - return ( diff --git a/editor/pages/to-code/index.tsx b/editor/pages/to-code/index.tsx index 0adaa184..2770eaae 100644 --- a/editor/pages/to-code/index.tsx +++ b/editor/pages/to-code/index.tsx @@ -69,15 +69,8 @@ export default function Page() { if (file) { let val: EditorSnapshot; - const pages = file.document.children.map((page) => ({ - id: page.id, - name: page.name, - children: page["children"]?.map((child) => { - const _mapped = mapper.mapFigmaRemoteToFigma(child); - return convert.intoReflectNode(_mapped); - }), - type: "design", - })); + const components = warmup.componentsFrom(file); + const pages = warmup.pagesFrom(file); if (prevstate) { val = { @@ -115,6 +108,7 @@ export default function Page() { input: null, key: _input.file, pages: pages, + components: components, }, selectedPage: warmup.selectedPage(prevstate, pages, null), }; diff --git a/editor/scaffolds/editor/editor.tsx b/editor/scaffolds/editor/editor.tsx index cc010dde..ce4920bf 100644 --- a/editor/scaffolds/editor/editor.tsx +++ b/editor/scaffolds/editor/editor.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useRef, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import styled from "@emotion/styled"; import { useRouter } from "next/router"; import { DefaultEditorWorkspaceLayout } from "layouts/default-editor-workspace-layout"; @@ -19,7 +19,6 @@ import { ImageRepository, MainImageRepository, } from "@design-sdk/core/assets-repository"; -import { personal } from "@design-sdk/figma-auth-store"; import { useFigmaAccessToken } from "hooks"; import { get_framework_config } from "query/to-code-options-from-query"; import { CodeOptionsControl } from "components/codeui-code-options-control"; @@ -31,7 +30,6 @@ import { } from "utils/design-query"; import { vanilla_presets } from "@grida/builder-config-preset"; import { EditorSkeleton } from "./skeleton"; -import { MonacoEmptyMock } from "components/code-editor/monaco-mock-empty"; import { colors } from "theme"; export function Editor() { @@ -61,7 +59,11 @@ export function Editor() { find_node_by_id_under_inpage_nodes(targetId, thisPageNodes) || null; const root = thisPageNodes - ? container_of_target && DesignInput.fromDesign(container_of_target) + ? container_of_target && + DesignInput.fromDesignWithComponents({ + design: container_of_target, + components: state.design.components, + }) : state.design?.input; const targetted = @@ -246,43 +248,14 @@ export function Editor() { {wstate.preferences.debug_mode && ( - -
-
- -
- {(root.entry.origin === "INSTANCE" || - root.entry.origin === "COMPONENT") && ( - - )} -
- -
- -
-
- -
-
+ +
)} @@ -292,6 +265,59 @@ export function Editor() { ); } +const Debugger = ({ + id, + file, + type, + entry, + widget, +}: { + type: string; + id: string; + file: string; + entry: any; + widget: any; +}) => { + const router = useRouter(); + + return ( +
+
+ +
+ {(type === "INSTANCE" || type === "COMPONENT") && ( + + )} +
+ +
+ +
+
+ +
+
+ ); +}; + const CodeEditorContainer = styled.div` display: flex; flex-direction: column; diff --git a/editor/scaffolds/editor/warmup.ts b/editor/scaffolds/editor/warmup.ts index 2b0994a8..906f57bd 100644 --- a/editor/scaffolds/editor/warmup.ts +++ b/editor/scaffolds/editor/warmup.ts @@ -1,6 +1,7 @@ import { createPendingWorkspaceState, EditorSnapshot, + FigmaReflectRepository, WorkspaceState, } from "core/states"; import { createInitialWorkspaceState } from "core/states"; @@ -9,6 +10,10 @@ import { PendingState } from "core/utility-types"; import { DesignInput } from "@designto/config/input"; import { TargetNodeConfig } from "query/target-node"; import { WorkspaceAction } from "core/actions"; +import { FileResponse } from "@design-sdk/figma-remote-types"; +import { convert } from "@design-sdk/figma-node-conversion"; +import { mapper } from "@design-sdk/figma-remote"; +import { find, visit } from "tree-visit"; const pending_workspace_state = createPendingWorkspaceState(); // @@ -38,6 +43,61 @@ export function initialReducer( } } +export function pagesFrom(file: FileResponse): FigmaReflectRepository["pages"] { + return file.document.children.map((page) => ({ + id: page.id, + name: page.name, + children: page["children"]?.map((child) => { + const _mapped = mapper.mapFigmaRemoteToFigma(child); + return convert.intoReflectNode(_mapped); + }), + type: "design", + })); +} + +/** + * only fetch in-file components. components from shared-library (external file) won't be loaded. + * @param file + * @returns + */ +export function componentsFrom( + file: FileResponse +): FigmaReflectRepository["components"] { + const tomap = (a, v) => ({ ...a, [v.id]: v }); + + // only fetch in-file components. components from shared-library (external file) won't be loaded. + const components_in_file = []; + visit<{ id: string; type: string }>(file.document, { + getChildren: (node) => { + if ("children" in node) return node["children"]; + return []; + }, + onEnter: (node) => { + if (node["type"] == "COMPONENT") { + components_in_file.push(node); + } + }, + }); + + // return components_in_file.reduce(tomap, {}); + + return Object.keys(file.components) + .map((k) => { + const id = k; + const meta = file.components[k]; + const master = components_in_file.find((c) => c.id === id); + if (!master) return; + return { + key: meta.key, // only available with api response. the hash key of current version of component for another api call. (not used) + id: master.id, + name: master.name, + ...master, + }; + }) + .filter((c) => c) + .reduce(tomap, {}); +} + export function initializeDesign(design: TargetNodeConfig): EditorSnapshot { return { selectedNodes: [design.node], @@ -45,6 +105,8 @@ export function initializeDesign(design: TargetNodeConfig): EditorSnapshot { selectedPage: null, design: { pages: [], + components: null, + // styles: null, key: design.file, input: DesignInput.fromApiResponse({ ...design, diff --git a/packages/builder-config/input/design-input.ts b/packages/builder-config/input/design-input.ts index f2e971b2..19342be3 100644 --- a/packages/builder-config/input/design-input.ts +++ b/packages/builder-config/input/design-input.ts @@ -1,6 +1,7 @@ import type { ReflectSceneNode } from "@design-sdk/core"; import { mapGrandchildren } from "@design-sdk/core/utils"; import { NodeRepository } from "@design-sdk/figma"; +import type { ComponentNode } from "@design-sdk/figma"; import { RawNodeResponse } from "@design-sdk/figma-remote"; export interface IDesignInput { @@ -35,15 +36,25 @@ export class DesignInput implements IDesignInput { } static fromDesign(design: ReflectSceneNode): DesignInput { - const _allnodes = mapGrandchildren(design, 0, { - includeThis: true, - ignoreGroup: false, + const repository = new NodeRepository({ + // components not supported for `fromdesign` + components: null, + nodes: this._flat_all(design), }); + return new DesignInput({ entry: design, repository: repository }); + } + + static fromDesignWithComponents({ + design, + components, + }: { + design: ReflectSceneNode; + components: { [key: string]: ComponentNode } | ComponentNode[]; + }) { const repository = new NodeRepository({ - // TODO: components not supported for `fromdesign` - components: [], - nodes: [...(_allnodes as any)], + components: Object.values(components), + nodes: this._flat_all(design), }); return new DesignInput({ entry: design, repository: repository }); @@ -56,15 +67,17 @@ export class DesignInput implements IDesignInput { raw: RawNodeResponse; entry: ReflectSceneNode; }): DesignInput { - const _allnodes = mapGrandchildren(entry, 0, { - includeThis: true, - ignoreGroup: false, - }); - const repository = new NodeRepository({ components: [...(Object.values(raw.components) as any)], - nodes: [...(_allnodes as any)], + nodes: this._flat_all(entry), }); return new DesignInput({ entry: entry, repository: repository }); } + + private static _flat_all(entry) { + return mapGrandchildren(entry, 0, { + includeThis: true, + ignoreGroup: false, + }); + } } From e205f2c964332b9f53a9a09c18ce36fbd4ddf690 Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Wed, 29 Dec 2021 02:12:24 +0900 Subject: [PATCH 03/12] (ignore) --- editor/core/states/workspace-initial-state.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/core/states/workspace-initial-state.ts b/editor/core/states/workspace-initial-state.ts index 59c9828d..b65a3304 100644 --- a/editor/core/states/workspace-initial-state.ts +++ b/editor/core/states/workspace-initial-state.ts @@ -25,8 +25,8 @@ export function createPendingWorkspaceState(): WorkspaceState { return { history: createPendingHistoryState(), preferences: { - debug_mode: false, - enable_preview_feature_components_support: true, + debug_mode: null, + enable_preview_feature_components_support: null, preview_runner_framework_config: null, framework_config: null, }, From 4b8a7cd8683bf889fc01c21e0d1b7d054cd16330 Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Wed, 29 Dec 2021 02:13:46 +0900 Subject: [PATCH 04/12] add JsxText attribute support on instanciation of component --- externals/coli | 2 +- externals/design-sdk | 2 +- .../widget-instanciation/index.ts | 39 ++++++++- .../designto-code/universal/design-to-code.ts | 2 +- .../compose-instanciation.ts | 16 ++-- .../tokens-to-web-widget/index.ts | 5 ++ packages/support-components/define.ts | 84 +++++++++++++++---- packages/support-components/main.ts | 5 +- 8 files changed, 126 insertions(+), 29 deletions(-) diff --git a/externals/coli b/externals/coli index 83d3cb54..7beb540c 160000 --- a/externals/coli +++ b/externals/coli @@ -1 +1 @@ -Subproject commit 83d3cb546b753859cb23ef2a79346ac438aae563 +Subproject commit 7beb540c885c7b40bf163004a182d60fbdf001ce diff --git a/externals/design-sdk b/externals/design-sdk index 6e2e8b0c..95431cad 160000 --- a/externals/design-sdk +++ b/externals/design-sdk @@ -1 +1 @@ -Subproject commit 6e2e8b0cebad3f5808c72864e897969e50f919d3 +Subproject commit 95431cadd54f91b9cafe49822b1f4fdd2285dd9c diff --git a/packages/builder-web-core/widget-instanciation/index.ts b/packages/builder-web-core/widget-instanciation/index.ts index 8a005e53..f615e97e 100644 --- a/packages/builder-web-core/widget-instanciation/index.ts +++ b/packages/builder-web-core/widget-instanciation/index.ts @@ -1,20 +1,53 @@ import { WidgetKey } from "../widget-key"; import { JSXElementConfig, JsxWidget } from "../widget-core"; -import { JSX } from "coli"; +import { JSX, JSXAttribute, Types } from "coli"; export class InstanciationElement extends JsxWidget { readonly identifier: string; - // TODO: support arguments + readonly arguments: { [key: string]: any }; - constructor({ key, identifier }: { key: WidgetKey; identifier: string }) { + constructor({ + key, + identifier, + arguments: _arguments, + }: { + key: WidgetKey; + identifier: string; + arguments: { [key: string]: any }; + }) { super({ key }); this.identifier = identifier; + this.arguments = _arguments ?? {}; } jsxConfig(): JSXElementConfig { + const _attrs = this.makeJsxAttributes(); return { type: "tag-and-attr", tag: JSX.identifier(this.identifier), + attributes: _attrs, }; } + + private makeJsxAttributes() { + const jsxValue = (value: any) => { + switch (typeof value) { + case "undefined": + return JSX.exp(undefined); + case "string": + return JSX.text(value, "template-literal"); + case "number": + return JSX.number(value); + default: + console.error(`Unsupported type of value: ${typeof value}`); + } + }; + + return Object.keys(this.arguments) + .map((key, index) => { + const rec = this.arguments[key]; + return new JSXAttribute(rec.key, jsxValue(rec.value)); + }) + .filter((a) => a); + } } diff --git a/packages/designto-code/universal/design-to-code.ts b/packages/designto-code/universal/design-to-code.ts index c6ab27c8..6c0e7ba5 100644 --- a/packages/designto-code/universal/design-to-code.ts +++ b/packages/designto-code/universal/design-to-code.ts @@ -72,7 +72,7 @@ export async function designToCode({ console.log("reusable_widget_tree", reusable_widget_tree); // TODO: WIP } catch (_) { - console.error(_); + console.error("error while building reusable widget tree.", _); } } diff --git a/packages/designto-web/tokens-to-web-widget/compose-instanciation.ts b/packages/designto-web/tokens-to-web-widget/compose-instanciation.ts index 40c7bd61..cb9e8671 100644 --- a/packages/designto-web/tokens-to-web-widget/compose-instanciation.ts +++ b/packages/designto-web/tokens-to-web-widget/compose-instanciation.ts @@ -1,18 +1,24 @@ import { Composer } from "."; import * as reusable from "@code-features/component/tokens"; import * as web from "@web-builder/core"; +import { nameit, NameCases } from "coli"; export function compose_instanciation( widget: reusable.InstanceWidget, - child_composer: Composer + child_composer: Composer // not used ) { const masterkey = widget.meta.master.key; + + const identifier = nameit(widget.meta.master.key.originName, { + case: NameCases.pascal, + }).name; + return new web.InstanciationElement({ key: { - name: "foo", - id: masterkey.id, + name: "ExampleUsageOf_" + identifier, // FIXME: should not use identifier as name + id: widget.key.id, }, - // TODO: fix this - identifier: "foo", + identifier: identifier, + arguments: widget.meta.arguments, }); } diff --git a/packages/designto-web/tokens-to-web-widget/index.ts b/packages/designto-web/tokens-to-web-widget/index.ts index b7a10482..9c0aed7b 100644 --- a/packages/designto-web/tokens-to-web-widget/index.ts +++ b/packages/designto-web/tokens-to-web-widget/index.ts @@ -232,6 +232,10 @@ function compose( // end of logic gate // ------------------------------------- else { + if (thisWebWidget) + throw new Error( + "internal error. this final exception gate should not be entered since there is already a composed widget." + ); // todo - handle case more specific thisWebWidget = new web.ErrorWidget({ key: _key, @@ -239,6 +243,7 @@ function compose( widget.key.originName }" type of "${widget._type}" - ${JSON.stringify(widget.key)}`, }); + console.warn("not handled", widget); } // ------------------------------------- // ------------------------------------- diff --git a/packages/support-components/define.ts b/packages/support-components/define.ts index bcbe3fdc..536389ae 100644 --- a/packages/support-components/define.ts +++ b/packages/support-components/define.ts @@ -1,4 +1,4 @@ -import { Figma, ReflectSceneNode } from "@design-sdk/figma"; +import { ComponentNode, Figma, ReflectSceneNode } from "@design-sdk/figma"; import { compare_instance_with_master, InstanceDiff_1on1, @@ -11,7 +11,9 @@ import { } from "./tokens/token-master-component"; import { InstanceMetaToken } from "./tokens/token-instance"; import { keyFromNode } from "@designto/token/key"; - +import { NameCases, nameit, ScopedVariableNamer } from "coli"; +import { ReservedKeywordPlatformPresets } from "@coli.codes/naming/reserved"; +import { visit } from "tree-visit"; type IDMappable = | { [key: string]: T; @@ -26,6 +28,25 @@ function findIn(map: IDMappable, id: string) { } } +function findDeepUnderComponent(component: ComponentNode, id: string) { + let found = null; + visit<{ id; children }>(component, { + getChildren: (node) => { + if ("children" in node) { + return node.children; + } + return []; + }, + onEnter: (node) => { + if (node.id === id) { + found = node; + return "stop"; + } + }, + }); + return found; +} + // based on default strategy // WIP @@ -70,12 +91,9 @@ function define_props(diff: NodeDiff): PropertyDefinition[] { if (!diff.diff) return; const masterId = diff.ids[0]; const instanceId = diff.ids[1]; - console.log("diff.type", diff.type); switch (diff.type) { case "instance-to-master": - throw "instance-to-master - not implemented"; // TODO: return define_props__instance(diff as any) as any; - break; case "text-node": return [ diff.characters.diff @@ -88,8 +106,7 @@ function define_props(diff: NodeDiff): PropertyDefinition[] { } : null, // TODO: add text styles diff support - ]; - break; + ].filter((d) => d); } } @@ -103,15 +120,50 @@ const define_props__instance = (diff: InstanceDiff_1on1) => { }; export function make_instance_component_meta({ entry, components }: Input) { + const propertyNamer = new ScopedVariableNamer( + "property", + ReservedKeywordPlatformPresets.universal + ); + const property_meta = overrided_property_meta({ entry, components }); + const masterId = property_meta.ids[0]; + const master = findIn(components, masterId); const properties = define_props__instance(property_meta).flat(); - const master = new MasterComponentMetaToken({ - key: keyFromNode(findIn(components, property_meta.ids[0])), + const __name_cache = {}; + /** + * + * @param propertyOriginId - the origin node of the property will be targetted. e.g. in `master(group(text))`, the master's text's id will be used. + * @returns + */ + const get_property_key = (propertyOriginId?: string) => { + const originNodeName = findDeepUnderComponent( + master, + propertyOriginId + )?.name; + + if (originNodeName) { + const { name, register } = propertyNamer.nameit(originNodeName, { + case: NameCases.camel, + register: false, + }); + if (__name_cache[propertyOriginId]) { + return __name_cache[propertyOriginId]; + } else { + __name_cache[propertyOriginId] = name; + register(); + return name; + } + } + throw new Error("origin layer does not contain a valid name"); + }; + + const masterMeta = new MasterComponentMetaToken({ + key: keyFromNode(findIn(components, masterId)), properties: properties.map((p) => { return >{ - key: p.type, + key: get_property_key(p.master), type: p.type, defaultValue: p.default_value, link: { @@ -124,15 +176,15 @@ export function make_instance_component_meta({ entry, components }: Input) { }, }; }), - child: findIn(components, property_meta.ids[0]), + child: findIn(components, masterId), }); - const entryInstance = new InstanceMetaToken({ - master: master, + const entryInstanceMeta = new InstanceMetaToken({ + master: masterMeta, key: keyFromNode(entry), arguments: properties.reduce(function (result, item, index, array) { result[item.type] = { - key: item.type, + key: get_property_key(item.master), value: item.overrided_value, }; return result; @@ -140,8 +192,8 @@ export function make_instance_component_meta({ entry, components }: Input) { }); return new ComponentsUsageRepository({ - components: [master], - usage: { [entry.id]: entryInstance }, + components: [masterMeta], + usage: { [entry.id]: entryInstanceMeta }, }); } diff --git a/packages/support-components/main.ts b/packages/support-components/main.ts index cc6f363c..b187edbd 100644 --- a/packages/support-components/main.ts +++ b/packages/support-components/main.ts @@ -28,7 +28,6 @@ export function reusable({ */ entry: RenderObjectWidget; }): ReusableWidgetResult { - console.log("repository", repository); // all instances in the input scope const instances = repository.nodes.filter( (node) => node.origin === "INSTANCE" @@ -41,11 +40,13 @@ export function reusable({ const components = component_use_repository.components.map(composeComponentMeta); - return { + const _ = { // asumming root is always a multi child widget tree: composeInstanciationTree(entry, repository, component_use_repository), components: components, }; + // console.log("reusable", _); + return _; } function composeInstanciationTree( From 34e9e42e2a51d0b78cae66f6eda5536e683b9bd9 Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Wed, 29 Dec 2021 05:42:29 +0900 Subject: [PATCH 05/12] add `forMasterComponent` DesignInput initializer --- editor/scaffolds/editor/editor.tsx | 14 +++++++++---- packages/builder-config/input/design-input.ts | 20 +++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/editor/scaffolds/editor/editor.tsx b/editor/scaffolds/editor/editor.tsx index ce4920bf..75648b6c 100644 --- a/editor/scaffolds/editor/editor.tsx +++ b/editor/scaffolds/editor/editor.tsx @@ -60,10 +60,16 @@ export function Editor() { const root = thisPageNodes ? container_of_target && - DesignInput.fromDesignWithComponents({ - design: container_of_target, - components: state.design.components, - }) + (container_of_target.origin === "COMPONENT" + ? DesignInput.forMasterComponent({ + master: container_of_target, + all: state.design.pages, + components: state.design.components, + }) + : DesignInput.fromDesignWithComponents({ + design: container_of_target, + components: state.design.components, + })) : state.design?.input; const targetted = diff --git a/packages/builder-config/input/design-input.ts b/packages/builder-config/input/design-input.ts index 19342be3..e1966a43 100644 --- a/packages/builder-config/input/design-input.ts +++ b/packages/builder-config/input/design-input.ts @@ -60,6 +60,26 @@ export class DesignInput implements IDesignInput { return new DesignInput({ entry: design, repository: repository }); } + static forMasterComponent({ + all, + master, + components, + }: { + /** + * usually pages. Document#pages + */ + all: { id: string; name: string; children: ReflectSceneNode[] }[]; + master: ReflectSceneNode; + components: { [key: string]: ComponentNode } | ComponentNode[]; + }) { + const repository = new NodeRepository({ + components: Object.values(components), + nodes: all.map((p) => p.children.map(this._flat_all).flat()).flat(), + }); + + return new DesignInput({ entry: master, repository: repository }); + } + static fromApiResponse({ raw, entry, From 2ab61321b8838b33388b74b02c1f328e18737619 Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Wed, 29 Dec 2021 05:52:19 +0900 Subject: [PATCH 06/12] skip second entry if no asset to fetch for result proc --- editor/scaffolds/editor/editor.tsx | 28 ++++++++++++++++------------ externals/design-sdk | 2 +- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/editor/scaffolds/editor/editor.tsx b/editor/scaffolds/editor/editor.tsx index 75648b6c..cf19567d 100644 --- a/editor/scaffolds/editor/editor.tsx +++ b/editor/scaffolds/editor/editor.tsx @@ -137,12 +137,14 @@ export function Editor() { }).then(on_result); // build final code with asset fetch - designToCode({ - input: root, - framework: framework_config, - asset_config: { asset_repository: MainImageRepository.instance }, - build_config: build_config, - }).then(on_result); + if (!MainImageRepository.instance.empty) { + designToCode({ + input: root, + framework: framework_config, + asset_config: { asset_repository: MainImageRepository.instance }, + build_config: build_config, + }).then(on_result); + } } }, [targetted?.id, framework_config?.framework]); @@ -176,12 +178,14 @@ export function Editor() { }, }).then(on_preview_result); - designToCode({ - input: root, - build_config: build_config, - framework: vanilla_presets.vanilla_default, - asset_config: { asset_repository: MainImageRepository.instance }, - }).then(on_preview_result); + if (!MainImageRepository.instance.empty) { + designToCode({ + input: root, + build_config: build_config, + framework: vanilla_presets.vanilla_default, + asset_config: { asset_repository: MainImageRepository.instance }, + }).then(on_preview_result); + } } }, [targetted?.id] diff --git a/externals/design-sdk b/externals/design-sdk index 95431cad..84bef6eb 160000 --- a/externals/design-sdk +++ b/externals/design-sdk @@ -1 +1 @@ -Subproject commit 95431cadd54f91b9cafe49822b1f4fdd2285dd9c +Subproject commit 84bef6eb6d328fca93fd431aae864fa5fdee2775 From 79e73cf72ab22bd37b0ffdab5ad63af4e26037e9 Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Wed, 29 Dec 2021 06:09:51 +0900 Subject: [PATCH 07/12] clean logging --- .../from-reusable-widget-tree.ts | 4 ++-- .../react-styled-components-module-builder.ts | 23 +++++++++---------- .../designto-code/universal/design-to-code.ts | 23 +++++++++++++------ packages/designto-react/app/index.ts | 2 +- .../tokens-to-web-widget/index.ts | 4 ---- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/packages/builder-web-react/react-styled-component-widget/from-reusable-widget-tree.ts b/packages/builder-web-react/react-styled-component-widget/from-reusable-widget-tree.ts index 082cfdac..1d1a2811 100644 --- a/packages/builder-web-react/react-styled-component-widget/from-reusable-widget-tree.ts +++ b/packages/builder-web-react/react-styled-component-widget/from-reusable-widget-tree.ts @@ -31,9 +31,9 @@ export function finalizeReactReusable_StyledComponents__Experimental({ }; const token = hanlde(tree); - console.log("token", token); + console.log("from-reusable-widget-tree::token", { token, tree }); const webwi = buildWebWidgetFromTokens(token); - console.log("webwi", webwi); + console.log("from-reusable-widget-tree::web-widget", webwi); const builder = new ReactStyledComponentsBuilder({ entry: webwi, config: { diff --git a/packages/builder-web-react/react-styled-component-widget/react-styled-components-module-builder.ts b/packages/builder-web-react/react-styled-component-widget/react-styled-components-module-builder.ts index aab80cac..deac26bd 100644 --- a/packages/builder-web-react/react-styled-component-widget/react-styled-components-module-builder.ts +++ b/packages/builder-web-react/react-styled-component-widget/react-styled-components-module-builder.ts @@ -106,9 +106,9 @@ export class ReactStyledComponentsBuilder { partDeclarations() { return Array.from(this.styledConfigWidgetMap.keys()) .map((k) => { - return (this.styledConfigWidgetMap.get( - k - ) as StyledComponentJSXElementConfig).styledComponent; + return ( + this.styledConfigWidgetMap.get(k) as StyledComponentJSXElementConfig + ).styledComponent; }) .filter((s) => s); } @@ -170,23 +170,21 @@ export class ReactStyledComponentWidgetModuleExportable { }); file.imports(...this.imports); - console.log("exporting", exporting); + // console.log("exporting", exporting); switch (exporting.type) { case "export-default-anonymous-functional-component": { // exporting.declaration_syntax_choice; // exporting.export_declaration_syntax_choice; // exporting.exporting_position; - const export_default_anaonymous_functional_component = new FunctionDeclaration( - undefined, - { + const export_default_anaonymous_functional_component = + new FunctionDeclaration(undefined, { body: this.body, modifiers: { default: SyntaxKind.DefaultKeyword, export: SyntaxKind.ExportKeyword, }, - } - ); + }); file.declare(export_default_anaonymous_functional_component); file.declare(...this.declarations); break; @@ -219,9 +217,10 @@ export class ReactStyledComponentWidgetModuleExportable { ); break; case "with-declaration": - const _exported_named_function_declaration = add_export_keyword_modifier_to_declaration( - named_function_declaration - ); + const _exported_named_function_declaration = + add_export_keyword_modifier_to_declaration( + named_function_declaration + ); file.declare(_exported_named_function_declaration); file.declare(...this.declarations); break; diff --git a/packages/designto-code/universal/design-to-code.ts b/packages/designto-code/universal/design-to-code.ts index 6c0e7ba5..93d1ef93 100644 --- a/packages/designto-code/universal/design-to-code.ts +++ b/packages/designto-code/universal/design-to-code.ts @@ -37,13 +37,16 @@ export async function designToCode({ asset_config: AssetsConfig; }): Promise { if (process.env.NODE_ENV === "development") { - console.info( - "dev: starting designtocode with user input", - input, - framework, - build_config, - asset_config - ); + if (framework.framework == "vanilla") { + } else { + console.info( + "dev: starting designtocode with user input", + input, + framework, + build_config, + asset_config + ); + } } // post token processing @@ -143,6 +146,12 @@ export async function designToReact({ !input.reusable_widget_tree ) { const reactwidget = toreact.buildReactWidget(input.widget); + if (process.env.NODE_ENV === "development") { + console.info("dev::", "final web token composed", { + input: input.widget, + reactwidget, + }); + } const res = toreact.buildReactApp(reactwidget, react_config); // ------------------------------------------------------------------------ diff --git a/packages/designto-react/app/index.ts b/packages/designto-react/app/index.ts index 0104fcd6..214d0ed6 100644 --- a/packages/designto-react/app/index.ts +++ b/packages/designto-react/app/index.ts @@ -33,7 +33,7 @@ export function buildReactApp( export function buildReactWidget(widget: Widget) { assert( - widget, + widget instanceof Widget, "A valid reflect widget manifest should be passed as an input. none was passed." ); diff --git a/packages/designto-web/tokens-to-web-widget/index.ts b/packages/designto-web/tokens-to-web-widget/index.ts index 9c0aed7b..54d17d52 100644 --- a/packages/designto-web/tokens-to-web-widget/index.ts +++ b/packages/designto-web/tokens-to-web-widget/index.ts @@ -23,10 +23,6 @@ export function buildWebWidgetFromTokens(widget: core.Widget): JsxWidget { is_root: true, }); - if (process.env.NODE_ENV === "development") { - console.info("dev::", "final web token composed", composed); - } - return composed; } From 4670d2e202bea84d459715d2c0b3d716bf467ccc Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Wed, 29 Dec 2021 06:10:30 +0900 Subject: [PATCH 08/12] fix widget being unwrapped, loosing instanceof compatibility. using re-assign --- packages/support-components/main.ts | 47 +++++++++++++---------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/packages/support-components/main.ts b/packages/support-components/main.ts index b187edbd..db965e77 100644 --- a/packages/support-components/main.ts +++ b/packages/support-components/main.ts @@ -57,15 +57,10 @@ function composeInstanciationTree( widget = unwrappedChild(widget); // unwrap child to reach original input. const { key, _type: _widget_type } = widget; const node = repository.get(key.id); - if (!node) { - console.warn( - "node not found", - key, - repository, - "this is a know issue when trying to find a masking group. this will be fixed in the future." - ); - return; - } + + // prettier-ignore + if (!node) { console.warn("node not found", key, repository, "this is a know issue when trying to find a masking group. this will be fixed in the future."); return; } + if (node.origin === "INSTANCE") { const instanceMeta = componentsUsageRepository.getUsageOf(node.id); const instance = new InstanceWidget({ @@ -78,25 +73,25 @@ function composeInstanciationTree( widget instanceof MultiChildRenderObjectWidget && widget.children.length > 0 ) { - return { - ...widget, - children: widget.children.map((c) => { - return composeInstanciationTree( - c, - repository, - componentsUsageRepository - ); - }), - }; - } else if (widget instanceof SingleChildRenderObjectWidget) { - return { - ...widget, - child: composeInstanciationTree( - widget.child, + // @ts-ignore + widget.children = widget.children.map((c) => { + return composeInstanciationTree( + c, repository, componentsUsageRepository - ), - }; + ); + }); + + return widget; + } else if (widget instanceof SingleChildRenderObjectWidget) { + // @ts-ignore + widget.child = composeInstanciationTree( + widget.child, + repository, + componentsUsageRepository + ); + + return widget; } else { return widget; } From 2721d07776682fed1f4b845dedc29012e0d1e4b7 Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Wed, 29 Dec 2021 07:22:39 +0900 Subject: [PATCH 09/12] add temporal fill property deligation --- packages/support-components/define.ts | 28 +++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/support-components/define.ts b/packages/support-components/define.ts index 536389ae..16ec49ac 100644 --- a/packages/support-components/define.ts +++ b/packages/support-components/define.ts @@ -105,8 +105,19 @@ function define_props(diff: NodeDiff): PropertyDefinition[] { use: instanceId, } : null, + diff.fills.diff + ? { + type: "text.fill", + default_value: JSON.stringify(diff.fills.values[0]), + overrided_value: JSON.stringify(diff.fills.values[1]), + master: masterId, + use: instanceId, + } + : null, // TODO: add text styles diff support ].filter((d) => d); + default: + throw "not handled yet - " + diff["type"]; } } @@ -116,7 +127,7 @@ const define_props__instance = (diff: InstanceDiff_1on1) => { return define_props(d); }) .flat() - .filter((d) => d); // remove nulls + .filter(Boolean); }; export function make_instance_component_meta({ entry, components }: Input) { @@ -137,7 +148,8 @@ export function make_instance_component_meta({ entry, components }: Input) { * @param propertyOriginId - the origin node of the property will be targetted. e.g. in `master(group(text))`, the master's text's id will be used. * @returns */ - const get_property_key = (propertyOriginId?: string) => { + const get_property_key = (type: string, propertyOriginId: string) => { + const uid = type + "-" + propertyOriginId; const originNodeName = findDeepUnderComponent( master, propertyOriginId @@ -148,10 +160,10 @@ export function make_instance_component_meta({ entry, components }: Input) { case: NameCases.camel, register: false, }); - if (__name_cache[propertyOriginId]) { - return __name_cache[propertyOriginId]; + if (__name_cache[uid]) { + return __name_cache[uid]; } else { - __name_cache[propertyOriginId] = name; + __name_cache[uid] = name; register(); return name; } @@ -163,7 +175,7 @@ export function make_instance_component_meta({ entry, components }: Input) { key: keyFromNode(findIn(components, masterId)), properties: properties.map((p) => { return >{ - key: get_property_key(p.master), + key: get_property_key(p.type, p.master), type: p.type, defaultValue: p.default_value, link: { @@ -184,7 +196,7 @@ export function make_instance_component_meta({ entry, components }: Input) { key: keyFromNode(entry), arguments: properties.reduce(function (result, item, index, array) { result[item.type] = { - key: get_property_key(item.master), + key: get_property_key(item.type, item.master), value: item.overrided_value, }; return result; @@ -219,6 +231,6 @@ function overrided_property_meta({ entry, components }: Input) { master: _master, components: Array.from(Object.values(components)), }); - // TODO: make meta based on diff + // TODO: make meta based on diff `{ diff, ... }` return diff; } From 2d4a96b2a43861bec89f47c8379b3536ffec5014 Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Wed, 29 Dec 2021 07:23:15 +0900 Subject: [PATCH 10/12] alt "inspect component" menu from button to link --- editor/scaffolds/editor/editor.tsx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/editor/scaffolds/editor/editor.tsx b/editor/scaffolds/editor/editor.tsx index cf19567d..89f3e054 100644 --- a/editor/scaffolds/editor/editor.tsx +++ b/editor/scaffolds/editor/editor.tsx @@ -31,6 +31,7 @@ import { import { vanilla_presets } from "@grida/builder-config-preset"; import { EditorSkeleton } from "./skeleton"; import { colors } from "theme"; +import Link from "next/link"; export function Editor() { const router = useRouter(); @@ -302,19 +303,17 @@ const Debugger = ({
{(type === "INSTANCE" || type === "COMPONENT") && ( - + )}
From 4aea792d1e5fa6368def8c29a5cde136fdb9fbf9 Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Wed, 29 Dec 2021 17:25:32 +0900 Subject: [PATCH 11/12] add nested hierachy property extraction support with design-sdk/design-diff --- externals/design-sdk | 2 +- packages/support-components/define.ts | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/externals/design-sdk b/externals/design-sdk index 84bef6eb..54d7aae0 160000 --- a/externals/design-sdk +++ b/externals/design-sdk @@ -1 +1 @@ -Subproject commit 84bef6eb6d328fca93fd431aae864fa5fdee2775 +Subproject commit 54d7aae0b6b1b41ca7de23f063f09de2c32e3fc0 diff --git a/packages/support-components/define.ts b/packages/support-components/define.ts index 16ec49ac..d7656589 100644 --- a/packages/support-components/define.ts +++ b/packages/support-components/define.ts @@ -2,6 +2,7 @@ import { ComponentNode, Figma, ReflectSceneNode } from "@design-sdk/figma"; import { compare_instance_with_master, InstanceDiff_1on1, + MultichildDiff, NodeDiff, } from "@design-sdk/diff"; import { ComponentsUsageRepository } from "./components-usage-repository"; @@ -93,7 +94,7 @@ function define_props(diff: NodeDiff): PropertyDefinition[] { const instanceId = diff.ids[1]; switch (diff.type) { case "instance-to-master": - return define_props__instance(diff as any) as any; + return define_props__instance(diff); case "text-node": return [ diff.characters.diff @@ -116,11 +117,22 @@ function define_props(diff: NodeDiff): PropertyDefinition[] { : null, // TODO: add text styles diff support ].filter((d) => d); + case "multi-child": + return define_props_multichild(diff); default: throw "not handled yet - " + diff["type"]; } } +const define_props_multichild = (diff: MultichildDiff) => { + return diff.values + .map((d) => { + return define_props(d); + }) + .flat() + .filter(Boolean); +}; + const define_props__instance = (diff: InstanceDiff_1on1) => { return diff.values .map((d) => { From 6b2581d2784ae03a94ae30dd9161bb0a065b1cc2 Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Wed, 29 Dec 2021 17:26:14 +0900 Subject: [PATCH 12/12] button widget temporarily disabled --- packages/designto-token/main.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/designto-token/main.ts b/packages/designto-token/main.ts index aecc5e19..c9a14a00 100644 --- a/packages/designto-token/main.ts +++ b/packages/designto-token/main.ts @@ -163,10 +163,11 @@ function handleNode( } // - button - - const _detect_if_button = detectIf.button(node); - if (_detect_if_button.result) { - return tokenizeButton.fromManifest(node, _detect_if_button.data); - } + // TODO: temporarily disabled - remove comment after button widget is ready + // const _detect_if_button = detectIf.button(node); + // if (_detect_if_button.result) { + // return tokenizeButton.fromManifest(node, _detect_if_button.data); + // } // ------------------------------------------------------------------------- // --------------------------- Detected tokens -----------------------------