From 3cc2dc631bdee82bca5008f99f8513505ed6ff55 Mon Sep 17 00:00:00 2001 From: Universe Date: Wed, 18 Jan 2023 23:35:17 +0900 Subject: [PATCH 01/18] add last-selected-page store by modes --- editor/core/reducers/editor-reducer.ts | 17 +++++++++-------- .../core/stores/editor-state-store-last-page.ts | 10 ++++++++++ editor/core/stores/index.ts | 1 + 3 files changed, 20 insertions(+), 8 deletions(-) create mode 100644 editor/core/stores/editor-state-store-last-page.ts create mode 100644 editor/core/stores/index.ts diff --git a/editor/core/reducers/editor-reducer.ts b/editor/core/reducers/editor-reducer.ts index 62ab8852..bd218c11 100644 --- a/editor/core/reducers/editor-reducer.ts +++ b/editor/core/reducers/editor-reducer.ts @@ -28,6 +28,7 @@ import q from "@design-sdk/query"; import assert from "assert"; import { getPageNode } from "utils/get-target-node"; import { nanoid } from "nanoid"; +import { last_page_by_mode } from "core/stores"; const _editor_path_name = "/files/[key]/"; @@ -57,10 +58,9 @@ export function editorReducer(state: EditorState, action: Action): EditorState { }; if (target === "design") { - // todo: this should be a last selection as well, not index 0. - draft.selectedPage = state.pages.find( - (p) => p.type === "figma-canvas" - ).id; + draft.selectedPage = + last_page_by_mode.get(target) || + state.pages.find((p) => p.type === "figma-canvas").id; } }); } else { @@ -78,10 +78,9 @@ export function editorReducer(state: EditorState, action: Action): EditorState { case "design": { // if previous mode was somehing else. if (state.mode.value !== "design") { - // todo: this should be a last selection as well, not index 0. - draft.selectedPage = state.pages.find( - (p) => p.type === "figma-canvas" - ).id; + draft.selectedPage = + last_page_by_mode.get(mode) || + state.pages.find((p) => p.type === "figma-canvas").id; break; } } @@ -473,6 +472,8 @@ const reducers = { const last_known_selections_of_this_page = _canvas_state_store.getLastSelection() ?? []; + + last_page_by_mode.set(state.mode.value, pageid); draft.selectedPage = pageid; draft.selectedNodes = last_known_selections_of_this_page; diff --git a/editor/core/stores/editor-state-store-last-page.ts b/editor/core/stores/editor-state-store-last-page.ts new file mode 100644 index 00000000..1ae7c10d --- /dev/null +++ b/editor/core/stores/editor-state-store-last-page.ts @@ -0,0 +1,10 @@ +import { EditorState } from "core/states"; + +export const last_page_by_mode = { + get: (mode: EditorState["mode"]["value"]): string | null => { + return localStorage.getItem("editor-state-store/lastpage-of-mode-" + mode); + }, + set: (mode: EditorState["mode"]["value"], page: string) => { + localStorage.setItem("editor-state-store/lastpage-of-mode-" + mode, page); + }, +}; diff --git a/editor/core/stores/index.ts b/editor/core/stores/index.ts new file mode 100644 index 00000000..b6358e2d --- /dev/null +++ b/editor/core/stores/index.ts @@ -0,0 +1 @@ +export * from "./editor-state-store-last-page" \ No newline at end of file From abeac6d5716fa24444924d0912fe5ac15e3a6ed7 Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 19 Jan 2023 15:25:22 +0900 Subject: [PATCH 02/18] update fsv action name --- editor-packages/editor-dashboard/core/action.ts | 14 +++++++------- editor-packages/editor-dashboard/core/provider.tsx | 12 ++++++------ editor-packages/editor-dashboard/core/reducer.ts | 14 +++++++------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/editor-packages/editor-dashboard/core/action.ts b/editor-packages/editor-dashboard/core/action.ts index 2de65173..7401424c 100644 --- a/editor-packages/editor-dashboard/core/action.ts +++ b/editor-packages/editor-dashboard/core/action.ts @@ -9,7 +9,7 @@ export type Action = export type ActionTypes = Action["type"]; export type NewSectionAction = { - type: "hierarchy/new-section"; + type: "fsv/new-section"; name: string; }; @@ -19,7 +19,7 @@ export type FilterAction = { }; export type MakeDirAction = { - type: "hierarchy/mkdir"; + type: "fsv/mkdir"; cwd: string; /** * name of the directory. if non provided, it will automatically assign a name like "Untitled 1" @@ -28,7 +28,7 @@ export type MakeDirAction = { }; export type MoveAction = { - type: "hierarchy/mv"; + type: "fsv/mv"; source: string[]; dest: string; }; @@ -36,21 +36,21 @@ export type MoveAction = { export type FoldUnfoldAllAction = FoldAllAction | UnfoldAllAction; export type FoldAllAction = { - type: "hierarchy/fold-all"; + type: "fsv/fold-all"; }; export type UnfoldAllAction = { - type: "hierarchy/unfold-all"; + type: "fsv/unfold-all"; }; export type FoldUnfoldAction = FoldAction | UnfoldAction; export type FoldAction = { - type: "hierarchy/fold"; + type: "fsv/fold"; path: string; }; export type UnfoldAction = { - type: "hierarchy/unfold"; + type: "fsv/unfold"; path: string; }; diff --git a/editor-packages/editor-dashboard/core/provider.tsx b/editor-packages/editor-dashboard/core/provider.tsx index 72e515d7..449f9d07 100644 --- a/editor-packages/editor-dashboard/core/provider.tsx +++ b/editor-packages/editor-dashboard/core/provider.tsx @@ -116,20 +116,20 @@ export function useDashboard() { const foldAll = useCallback(() => { dispatch({ - type: "hierarchy/fold-all", + type: "fsv/fold-all", }); }, [dispatch]); const unfoldAll = useCallback(() => { dispatch({ - type: "hierarchy/unfold-all", + type: "fsv/unfold-all", }); }, [dispatch]); const fold = useCallback( (path: string) => { dispatch({ - type: "hierarchy/fold", + type: "fsv/fold", path, }); }, @@ -139,7 +139,7 @@ export function useDashboard() { const unfold = useCallback( (path: string) => { dispatch({ - type: "hierarchy/unfold", + type: "fsv/unfold", path, }); }, @@ -149,7 +149,7 @@ export function useDashboard() { const mkdir = useCallback( (cwd: string, name?: string) => { dispatch({ - type: "hierarchy/mkdir", + type: "fsv/mkdir", cwd, name, }); @@ -160,7 +160,7 @@ export function useDashboard() { const mv = useCallback( (src: string[], dst: string) => { dispatch({ - type: "hierarchy/mv", + type: "fsv/mv", source: src, dest: dst, }); diff --git a/editor-packages/editor-dashboard/core/reducer.ts b/editor-packages/editor-dashboard/core/reducer.ts index 674d6ce0..efebca87 100644 --- a/editor-packages/editor-dashboard/core/reducer.ts +++ b/editor-packages/editor-dashboard/core/reducer.ts @@ -15,7 +15,7 @@ import type { DashboardFolderItem, DashboardState } from "./state"; export function reducer(state: DashboardState, action: Action): DashboardState { switch (action.type) { - case "hierarchy/new-section": { + case "fsv/new-section": { const { name } = action; return produce(state, (draft) => { draft.hierarchy.sections.push({ @@ -37,7 +37,7 @@ export function reducer(state: DashboardState, action: Action): DashboardState { }); } - case "hierarchy/mkdir": { + case "fsv/mkdir": { const { cwd: dirname, name: seedname } = action; return produce(state, (draft) => { const dir = draft.hierarchy.sections.find((s) => s.path === dirname); @@ -61,7 +61,7 @@ export function reducer(state: DashboardState, action: Action): DashboardState { }); } - case "hierarchy/mv": { + case "fsv/mv": { const { source, dest } = action; console.log("move", source, dest); @@ -98,14 +98,14 @@ export function reducer(state: DashboardState, action: Action): DashboardState { }); } - case "hierarchy/fold": { + case "fsv/fold": { const { path } = action; return produce(state, (draft) => { draft.hierarchyFoldings.push(path); }); } - case "hierarchy/unfold": { + case "fsv/unfold": { const { path } = action; return produce(state, (draft) => { draft.hierarchyFoldings = draft.hierarchyFoldings.filter( @@ -114,14 +114,14 @@ export function reducer(state: DashboardState, action: Action): DashboardState { }); } - case "hierarchy/fold-all": { + case "fsv/fold-all": { const {} = action; return produce(state, (draft) => { draft.hierarchyFoldings = state.hierarchy.sections.map((s) => s.path); }); } - case "hierarchy/unfold-all": { + case "fsv/unfold-all": { const {} = action; return produce(state, (draft) => { draft.hierarchyFoldings.length = 0; From 30412ed9bdc434176f013d6df537b452a13b4f92 Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 19 Jan 2023 19:41:14 +0900 Subject: [PATCH 03/18] fix height calc --- .../components/dashboard-item-card-scene.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/editor-packages/editor-dashboard/components/dashboard-item-card-scene.tsx b/editor-packages/editor-dashboard/components/dashboard-item-card-scene.tsx index 5080b9a4..a92ba9f5 100644 --- a/editor-packages/editor-dashboard/components/dashboard-item-card-scene.tsx +++ b/editor-packages/editor-dashboard/components/dashboard-item-card-scene.tsx @@ -31,14 +31,15 @@ function SceneCardPreview({ // max allowed zoom = 1 const scale = Math.min(maxWidth / scene.width, 1); - const { height, type } = scene; + const { height: h, type } = scene; + const height = h * scale; // fixme: this is somethimes NaN return (
From e69976026f25735e29f268c3a6e38f0755f3eb00 Mon Sep 17 00:00:00 2001 From: softmarshmallow Date: Tue, 24 Jan 2023 17:06:20 +0900 Subject: [PATCH 04/18] add type --- editor/scaffolds/editor/editor-preview-provider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/scaffolds/editor/editor-preview-provider.tsx b/editor/scaffolds/editor/editor-preview-provider.tsx index 0ec57f3d..cb249288 100644 --- a/editor/scaffolds/editor/editor-preview-provider.tsx +++ b/editor/scaffolds/editor/editor-preview-provider.tsx @@ -471,7 +471,7 @@ class FlutterDaemon { return FlutterDaemon.project; } - async save(content) { + async save(content: string) { await FlutterDaemon.project.writeFile("lib/main.dart", content, true); } From 19042b26dd2c4d2078090c60ab9119d4193b967b Mon Sep 17 00:00:00 2001 From: Universe Date: Wed, 29 Mar 2023 15:39:28 +0900 Subject: [PATCH 05/18] api mvp --- editor/pages/api/v1/code/index.ts | 147 ++++++++++++++++++++++++++++++ scripts/html-test/write-html.js | 15 +++ 2 files changed, 162 insertions(+) create mode 100644 editor/pages/api/v1/code/index.ts create mode 100644 scripts/html-test/write-html.js diff --git a/editor/pages/api/v1/code/index.ts b/editor/pages/api/v1/code/index.ts new file mode 100644 index 00000000..f916f3c9 --- /dev/null +++ b/editor/pages/api/v1/code/index.ts @@ -0,0 +1,147 @@ +import { designToCode, Result } from "@designto/code"; +import { DesignInput } from "@grida/builder-config/input"; +import { parseFileAndNodeId } from "@design-sdk/figma-url"; +import { fetchTargetAsReflect } from "@design-sdk/figma-remote"; +import { + ImageRepository, + MainImageRepository, +} from "@design-sdk/asset-repository"; +import { RemoteImageRepositories } from "@design-sdk/figma-remote/asset-repository"; +import type { FrameworkConfig } from "@grida/builder-config"; +import { defaultConfigByFramework } from "@grida/builder-config-preset"; +import { Language } from "@grida/builder-platform-types"; +import { formatCode } from "dart-style"; + +type FigmaAccessTokenType = "at" | "pat"; + +export default async function handler(req, res) { + // accept only post request + if (req.method !== "POST") { + res.status(405).json({ message: "method not allowed" }); + return; + } + + const figma_access_token: string = req.headers["x-figma-token"]; + + if (!figma_access_token) { + res.status(401).json({ + message: "No figma access token provided.", + }); + return; + } + + const figma_access_token_type: FigmaAccessTokenType = + figma_access_token.startsWith("figd") ? "pat" : "at"; + + const { uri, framework } = req.body; + try { + const src = await code({ + uri, + framework, + auth: + figma_access_token_type === "at" + ? { + accessToken: figma_access_token, + } + : { + personalAccessToken: figma_access_token, + }, + }); + + res.status(200).json({ + src, + }); + } catch (e) { + res.status(500).json({ + message: e.message, + stacktrace: e.stack, + }); + + throw e; + } +} + +async function code({ + auth, + uri, + framework, +}: { + auth: + | { + personalAccessToken: string; + } + | { accessToken: string }; + uri: string; + framework: FrameworkConfig; +}) { + // + + const res = parseFileAndNodeId(uri as string); + if (res) { + const { file: filekey, node } = res; + + console.log(`filekey: ${filekey}`, `node: ${node}`); + + // + const target = await fetchTargetAsReflect({ + file: filekey, + node, + auth: auth, + }); + + MainImageRepository.instance = new RemoteImageRepositories(target.file, { + authentication: auth, + }); + MainImageRepository.instance.register( + new ImageRepository( + "fill-later-assets", + "grida://assets-reservation/images/" + ) + ); + + const code = await designToCode({ + input: DesignInput.fromApiResponse({ + raw: target.raw, + entry: target.reflect!, + }), + framework: { + // fill missing configurations. + ...defaultConfigByFramework(framework.framework), + ...framework, + }, + asset_config: { asset_repository: MainImageRepository.instance }, + }); + + const src = postproc_src( + filesrc(code, framework.framework), + framework.language + ); + + return src; + } +} + +function filesrc( + code: Result, + framework: FrameworkConfig["framework"] +): string { + switch (framework) { + case "flutter": { + return code.code.raw; + } + default: + return code.scaffold.raw; + } +} + +function postproc_src(src: string, language: Language) { + if (language === Language.dart) { + const { code, error } = formatCode(src); + if (error) { + return src; + } + return code; + } + + return src; +} diff --git a/scripts/html-test/write-html.js b/scripts/html-test/write-html.js new file mode 100644 index 00000000..a287b454 --- /dev/null +++ b/scripts/html-test/write-html.js @@ -0,0 +1,15 @@ +// get txt file as cli input, write to out.html file (to remove the special characters like \n, \t, etc) + +const fs = require("fs"); +const path = require("path"); + +const input = process.argv[2]; +let txt = fs.readFileSync(path.join(__dirname, input), "utf8"); + +// remove special characters +txt = txt.replace(/\\n/g, "\n"); +txt = txt.replace(/\\t/g, "\t"); +txt = txt.replace(/\\r/g, "\r"); +txt = txt.replace(/\\"/g, '"'); + +fs.writeFileSync(path.join(__dirname, "out.html"), txt); From 4f1277ef8190d5bbb7910a82f42cae534525e45e Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 30 Mar 2023 11:26:28 +0900 Subject: [PATCH 06/18] mv --- code/README.md | 1 + code/index.ts | 98 +++++++++++++++++++++++++++++ code/package.json | 4 ++ editor/next.config.js | 1 + editor/pages/api/v1/code/index.ts | 100 +----------------------------- package.json | 69 +++++++++++---------- 6 files changed, 140 insertions(+), 133 deletions(-) create mode 100644 code/README.md create mode 100644 code/index.ts create mode 100644 code/package.json diff --git a/code/README.md b/code/README.md new file mode 100644 index 00000000..b9cb3660 --- /dev/null +++ b/code/README.md @@ -0,0 +1 @@ +# Grida API Core - This is not a Client Library diff --git a/code/index.ts b/code/index.ts new file mode 100644 index 00000000..91d17e06 --- /dev/null +++ b/code/index.ts @@ -0,0 +1,98 @@ +import { designToCode, Result } from "@designto/code"; +import { DesignInput } from "@grida/builder-config/input"; +import { parseFileAndNodeId } from "@design-sdk/figma-url"; +import { fetchTargetAsReflect } from "@design-sdk/figma-remote"; +import { + ImageRepository, + MainImageRepository, +} from "@design-sdk/asset-repository"; +import { RemoteImageRepositories } from "@design-sdk/figma-remote/asset-repository"; +import type { FrameworkConfig } from "@grida/builder-config"; +import { defaultConfigByFramework } from "@grida/builder-config-preset"; +import { Language } from "@grida/builder-platform-types"; +import { formatCode } from "dart-style"; + +export async function code({ + auth, + uri, + framework, +}: { + auth: + | { + personalAccessToken: string; + } + | { accessToken: string }; + uri: string; + framework: FrameworkConfig; +}) { + // + + const res = parseFileAndNodeId(uri as string); + if (res) { + const { file: filekey, node } = res; + + console.log(`filekey: ${filekey}`, `node: ${node}`); + + // + const target = await fetchTargetAsReflect({ + file: filekey, + node, + auth: auth, + }); + + MainImageRepository.instance = new RemoteImageRepositories(target.file, { + authentication: auth, + }); + MainImageRepository.instance.register( + new ImageRepository( + "fill-later-assets", + "grida://assets-reservation/images/" + ) + ); + + const code = await designToCode({ + input: DesignInput.fromApiResponse({ + raw: target.raw, + entry: target.reflect!, + }), + framework: { + // fill missing configurations. + ...defaultConfigByFramework(framework.framework), + ...framework, + }, + asset_config: { asset_repository: MainImageRepository.instance }, + }); + + const src = postproc_src( + filesrc(code, framework.framework), + framework.language + ); + + return src; + } +} + +function filesrc( + code: Result, + framework: FrameworkConfig["framework"] +): string { + switch (framework) { + case "flutter": { + return code.code.raw; + } + default: + return code.scaffold.raw; + } +} + +function postproc_src(src: string, language: Language) { + if (language === Language.dart) { + const { code, error } = formatCode(src); + if (error) { + return src; + } + return code; + } + + return src; +} diff --git a/code/package.json b/code/package.json new file mode 100644 index 00000000..f49ba224 --- /dev/null +++ b/code/package.json @@ -0,0 +1,4 @@ +{ + "name": "@grida/code", + "version": "0.0.0" +} diff --git a/editor/next.config.js b/editor/next.config.js index 27c1d11c..17e7557d 100644 --- a/editor/next.config.js +++ b/editor/next.config.js @@ -20,6 +20,7 @@ const packages = [ // ----------------------------- // region @designto-code + "@grida/code", "@designto/debugger", "@grida/builder-config", "@grida/builder-config-preset", diff --git a/editor/pages/api/v1/code/index.ts b/editor/pages/api/v1/code/index.ts index f916f3c9..ffb7f588 100644 --- a/editor/pages/api/v1/code/index.ts +++ b/editor/pages/api/v1/code/index.ts @@ -1,17 +1,4 @@ -import { designToCode, Result } from "@designto/code"; -import { DesignInput } from "@grida/builder-config/input"; -import { parseFileAndNodeId } from "@design-sdk/figma-url"; -import { fetchTargetAsReflect } from "@design-sdk/figma-remote"; -import { - ImageRepository, - MainImageRepository, -} from "@design-sdk/asset-repository"; -import { RemoteImageRepositories } from "@design-sdk/figma-remote/asset-repository"; -import type { FrameworkConfig } from "@grida/builder-config"; -import { defaultConfigByFramework } from "@grida/builder-config-preset"; -import { Language } from "@grida/builder-platform-types"; -import { formatCode } from "dart-style"; - +import { code } from "@grida/code"; type FigmaAccessTokenType = "at" | "pat"; export default async function handler(req, res) { @@ -60,88 +47,3 @@ export default async function handler(req, res) { throw e; } } - -async function code({ - auth, - uri, - framework, -}: { - auth: - | { - personalAccessToken: string; - } - | { accessToken: string }; - uri: string; - framework: FrameworkConfig; -}) { - // - - const res = parseFileAndNodeId(uri as string); - if (res) { - const { file: filekey, node } = res; - - console.log(`filekey: ${filekey}`, `node: ${node}`); - - // - const target = await fetchTargetAsReflect({ - file: filekey, - node, - auth: auth, - }); - - MainImageRepository.instance = new RemoteImageRepositories(target.file, { - authentication: auth, - }); - MainImageRepository.instance.register( - new ImageRepository( - "fill-later-assets", - "grida://assets-reservation/images/" - ) - ); - - const code = await designToCode({ - input: DesignInput.fromApiResponse({ - raw: target.raw, - entry: target.reflect!, - }), - framework: { - // fill missing configurations. - ...defaultConfigByFramework(framework.framework), - ...framework, - }, - asset_config: { asset_repository: MainImageRepository.instance }, - }); - - const src = postproc_src( - filesrc(code, framework.framework), - framework.language - ); - - return src; - } -} - -function filesrc( - code: Result, - framework: FrameworkConfig["framework"] -): string { - switch (framework) { - case "flutter": { - return code.code.raw; - } - default: - return code.scaffold.raw; - } -} - -function postproc_src(src: string, language: Language) { - if (language === Language.dart) { - const { code, error } = formatCode(src); - if (error) { - return src; - } - return code; - } - - return src; -} diff --git a/package.json b/package.json index b1d22965..d79361fc 100644 --- a/package.json +++ b/package.json @@ -1,35 +1,36 @@ { - "name": "designto.codes", - "homepage": "https://designto.codes/", - "repository": "https://github.com/gridaco/designto-code", - "license": "Apache 2.0", - "private": true, - "scripts": { - "checkout:all": "git submodule update --init --recursive", - "clean": "yarn lerna clean -y && yarn lerna bootstrap && yarn lerna exec 'rm -rf ./dist'", - "editor": "turbo run editor#dev", - "build": "turbo run build", - "lerna": "lerna" - }, - "workspaces": [ - "editor", - "editor-packages/*", - "packages/*", - "ui/editor-ui/packages/*" - ], - "resolutions": { - "@design-sdk/figma-node": "0.0.25", - "@reflect-ui/core": "0.0.9", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "@types/react": "18.0.24", - "@types/react-dom": "^18.0.8", - "csstype": "3.1.0" - }, - "devDependencies": { - "@types/node": "^18.6.3", - "lerna": "^4.0.0", - "turbo": "^1.4.2", - "typescript": "^4.7.4" - } -} \ No newline at end of file + "name": "designto.codes", + "homepage": "https://designto.codes/", + "repository": "https://github.com/gridaco/designto-code", + "license": "Apache 2.0", + "private": true, + "scripts": { + "checkout:all": "git submodule update --init --recursive", + "clean": "yarn lerna clean -y && yarn lerna bootstrap && yarn lerna exec 'rm -rf ./dist'", + "editor": "turbo run editor#dev", + "build": "turbo run build", + "lerna": "lerna" + }, + "workspaces": [ + "editor", + "code", + "editor-packages/*", + "packages/*", + "ui/editor-ui/packages/*" + ], + "resolutions": { + "@design-sdk/figma-node": "0.0.25", + "@reflect-ui/core": "0.0.9", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "@types/react": "18.0.24", + "@types/react-dom": "^18.0.8", + "csstype": "3.1.0" + }, + "devDependencies": { + "@types/node": "^18.6.3", + "lerna": "^4.0.0", + "turbo": "^1.4.2", + "typescript": "^4.7.4" + } +} From 5416b1e7346709e3d78fa5bcd32dc9e37c779d1f Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 30 Mar 2023 11:26:31 +0900 Subject: [PATCH 07/18] add api/v1/embed endpoint for embedding use --- editor/pages/api/v1/embed/index.ts | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 editor/pages/api/v1/embed/index.ts diff --git a/editor/pages/api/v1/embed/index.ts b/editor/pages/api/v1/embed/index.ts new file mode 100644 index 00000000..e6907723 --- /dev/null +++ b/editor/pages/api/v1/embed/index.ts @@ -0,0 +1,38 @@ +import { Language } from "@grida/builder-platform-types"; +import { code } from "@grida/code"; +import { Request, Response } from "express"; + +export default async function handler(req: Request, res: Response) { + // get the access token from the query string + const { figma, fpat, fat } = req.query; + + if (!figma) { + res.status(400).send("

No figma file url is provided

"); + return; + } + + if (!fpat && !fat) { + res.status(400).send("

No figma access token is provided

"); + return; + } + + try { + const src = await code({ + uri: figma as string, + framework: { + framework: "preview", + imgage_alt: {}, + language: Language.html, + }, + auth: { + accessToken: fat as string, + personalAccessToken: fpat as string, + }, + }); + + res.status(200).send(src); + } catch (e) { + res.status(500).send(`

${e.message}

${e.stack}
`); + throw e; + } +} From 2ceca275ab196e7194b140f0731984b8551e2acb Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 30 Mar 2023 13:55:32 +0900 Subject: [PATCH 08/18] init api pkg & types --- api/index.ts | 0 api/package.json | 4 +++ api/types.ts | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 api/index.ts create mode 100644 api/package.json create mode 100644 api/types.ts diff --git a/api/index.ts b/api/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/api/package.json b/api/package.json new file mode 100644 index 00000000..a6389900 --- /dev/null +++ b/api/package.json @@ -0,0 +1,4 @@ +{ + "name": "@grida/api", + "version": "0.0.0" +} diff --git a/api/types.ts b/api/types.ts new file mode 100644 index 00000000..8c593236 --- /dev/null +++ b/api/types.ts @@ -0,0 +1,65 @@ +import type { + FrameworkConfig, + VanillaFrameworkConfig, +} from "@grida/builder-config"; + +export type CodeResponse = FigmaToVanillaResponse; + +export const LICENSE_CE = { + "ce-use-of-generated-code": "Public Domain", + "ce-use-of-engine-source": "Apache-2.0", + "ce-use-for-commercial": "AGPL-3.0", +}; + +export type ApiEngineInfo = { + name: "code.grida.co/api/v1"; + version: "2023.1.1"; + license: "AGPL-3.0"; +}; + +export type D2CSourceMap = {}; + +export type FigmaInputPong = { + /** + * the id of entry node. usually it is the root node. + */ + entry: string; + /** + * the full node tree, including only essential information. like size, position, etc. + */ + node: object; +}; + +export interface BaseFigmaInputResponse { + figma: FigmaInputPong; +} + +export interface BaseResponse { + framework: FrameworkConfig; + engine: ApiEngineInfo; + version: 0; // for now, there is no versioning + license: typeof LICENSE_CE; +} + +export interface BaseWebFrameworkResponse extends BaseResponse { + src: string; + srcdoc: string; + srcmap: D2CSourceMap; + files: { + [key: string]: { + content: string; + }; + }; + + thumbnail: string; +} + +export interface VanillaCodeResponse extends BaseWebFrameworkResponse { + framework: VanillaFrameworkConfig; +} + +export interface FigmaToVanillaResponse + extends VanillaCodeResponse, + BaseFigmaInputResponse { + figma: FigmaInputPong; +} From 52b59188ef9608ae5bf0aadfda7ad69b87add771 Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 30 Mar 2023 13:56:24 +0900 Subject: [PATCH 09/18] init test dir --- api/__test__/.gitignore | 0 api/index.ts | 1 + 2 files changed, 1 insertion(+) create mode 100644 api/__test__/.gitignore diff --git a/api/__test__/.gitignore b/api/__test__/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/api/index.ts b/api/index.ts index e69de29b..eea524d6 100644 --- a/api/index.ts +++ b/api/index.ts @@ -0,0 +1 @@ +export * from "./types"; From f8ff169a5a0d53d0e5ac5d38c11e41d18c910138 Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 30 Mar 2023 14:35:27 +0900 Subject: [PATCH 10/18] update docs --- api/README.md | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 api/README.md diff --git a/api/README.md b/api/README.md new file mode 100644 index 00000000..27ddc7c1 --- /dev/null +++ b/api/README.md @@ -0,0 +1,136 @@ +# Grida Code API (Private Beta) + +## Usage (REST) + +### `POST /api/v1/code` + +Example + +```ts +import Axios from "axios"; + +const client = Axios.create({ + baseURL: "https://code.grida.co/api/v1", + headers: { + "Content-Type": "application/json", + "X-Figma-Access-Token": "figd_xxxxxxxxxx", + }, +}); + +client.post("code", { + // target node url formatted as https://www.figma.com/file/{fileKey}?node-id={nodeId} + // at this moment, the nodeId must be formatted as 00:00, not 00-00 + // Note: if you copy & paste the link from the fihma editor, you will get in the format of 00-00 (we are updating this) + figma: "https://www.figma.com/file/MikewnarPfXXXXX/?node-id=0%3A1", + framework: { + framework: "vanilla", // react, flutter, ... + }, +}); +``` + +#### Request Body + +**`body.figma`** + +An URL indicating the target node in Figma design. + +target node url formatted as `https://www.figma.com/file/{fileKey}?node-id={nodeId}` +at this moment, the nodeId must be formatted as `00:00`, not `00-00` url encoded value like `0%3A1` is also acceptable. + +Note: if you copy & paste the link from the fihma editor, you will get in the format of 00-00 (we are updating this) + +**`body.framework`** + +A Framework configuration used for generating code. Learn more at [Framework Configuration](https://grida.co/docs/cli#2-framework-configuration) + +#### Response + +```ts +// example of response +{ + warnings: [], + src: '', // do not use this + srcdoc: '......', + srcmap: { + // the mapping between the generated code and the design + // node-id : xpath + '123:123': '//div[@data-figma-node-id="123:123"]]' + }, + files:{ + 'index.hml': '......' + } + framework:{ + // the framework config used for generating code + // ... + }, + // (if the input design source is figma, you will get the brief summary about the used design) + figma:{ + file:{ + // #region original data ------ + name: "Exmaples", + lastModified: "2023-03-28T17:51:08Z", + thumbnailUrl: "https://s3-alpha.figma.com/thumbnails/dc85b86a-2502-4baa-a776-ce0972131a80", + version: "3247308401", + // #endregion original data ------ + } + + filekey: 'MikewnarPfXXXXX', + entry: '0:1', + json: "{}", + node: { + ... + } + } + engine: { + // the info of the engine used for generating code + name: 'code.grida.co/api/v1', + // the engibe version + version: '2023.1.1' + }, + // the preview image of the rendered html + thumbnail: 'https://xxx.s3.amazonaws.com/.../xxxxxx.png', + license: { + // the license info of the generated code and the api + // ... + } +} +``` + +- `warnings` - An array of warnings. If there is no warning, it will be an empty array. (This is usually a warning caused by poor design, which can be ignored) +- `src` - The generated code as a uri, a publicly accessible html file endpoint. +- `srcdoc` - The generated code as a bundled and concatenated string, which can be used to embed the code directly into your website. +- + +### `GET /api/v1/embed` + +We also provide an experimental embed API for embedding the generated code directly into your website with an iframe. + +Example + +```html + +``` + +#### URL Parameters + +**`figma`** +Same as `/v1/code` API's `figma` parameter. + +**`fpat`** or **`fat`** + +- fpat: Figma Personal Access Token (starting with `figd_`) +- fat: Figma Access Token + +Warning: For security reasons, we highly recommend using the Figma Access Token (which expires), instead of the Figma Personal Access Token (which never expires unless revoked). The Figma Personal Access Token is only used for development purpose. + +We are planning on providing a more secure way to use embed with the `fpat` in the future. + +The framework configuration for embed is `vanilla-preview` by default. We are planning on providing a way to customize the framework configuration in the future. + +## API Clients (Under Development) + +At this moment there is no publicly available API wrappers. If you are looking for use on your local machine, you van use [Grida CLI](https://grida.co/cli) From 2abc901bdd16be9c56c43ecf9b1eb458607f2040 Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 30 Mar 2023 14:49:00 +0900 Subject: [PATCH 11/18] update docs with types --- api/README.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/api/README.md b/api/README.md index 27ddc7c1..03d9428c 100644 --- a/api/README.md +++ b/api/README.md @@ -30,8 +30,24 @@ client.post("code", { #### Request Body +```ts +interface CodeRequets { + figma: FigmaNodeInput; + framework: Partial; +} +``` + **`body.figma`** +```ts +type FigmaNodeInput = + | string + | { url: string; version: string } + | { filekey: string; node: string; version: string }; +``` + +**Note** currently only `string` is supported. + An URL indicating the target node in Figma design. target node url formatted as `https://www.figma.com/file/{fileKey}?node-id={nodeId}` @@ -99,7 +115,6 @@ A Framework configuration used for generating code. Learn more at [Framework Con - `warnings` - An array of warnings. If there is no warning, it will be an empty array. (This is usually a warning caused by poor design, which can be ignored) - `src` - The generated code as a uri, a publicly accessible html file endpoint. - `srcdoc` - The generated code as a bundled and concatenated string, which can be used to embed the code directly into your website. -- ### `GET /api/v1/embed` @@ -131,6 +146,10 @@ We are planning on providing a more secure way to use embed with the `fpat` in t The framework configuration for embed is `vanilla-preview` by default. We are planning on providing a way to customize the framework configuration in the future. +## Request / Response Types Declarations + +See [./types.ts](./types.ts) + ## API Clients (Under Development) At this moment there is no publicly available API wrappers. If you are looking for use on your local machine, you van use [Grida CLI](https://grida.co/cli) From 92395a373ea932a31e56bb480740938f1f06b776 Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 30 Mar 2023 14:49:15 +0900 Subject: [PATCH 12/18] add request type decs --- api/types.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/api/types.ts b/api/types.ts index 8c593236..2797e0ca 100644 --- a/api/types.ts +++ b/api/types.ts @@ -3,6 +3,16 @@ import type { VanillaFrameworkConfig, } from "@grida/builder-config"; +export type FigmaNodeInput = + | string + | { url: string; version: string } + | { filekey: string; node: string; version: string }; + +export interface CodeRequets { + figma: FigmaNodeInput; + framework: Partial; +} + export type CodeResponse = FigmaToVanillaResponse; export const LICENSE_CE = { @@ -19,7 +29,16 @@ export type ApiEngineInfo = { export type D2CSourceMap = {}; +export type FigmaOriginalFileData = { + name: string; + lastModified: string; + thumbnailUrl: string; + version: string; +}; + export type FigmaInputPong = { + file?: FigmaOriginalFileData; + filekey: string; /** * the id of entry node. usually it is the root node. */ @@ -28,6 +47,7 @@ export type FigmaInputPong = { * the full node tree, including only essential information. like size, position, etc. */ node: object; + json: string; }; export interface BaseFigmaInputResponse { @@ -39,6 +59,7 @@ export interface BaseResponse { engine: ApiEngineInfo; version: 0; // for now, there is no versioning license: typeof LICENSE_CE; + warnings: string[]; } export interface BaseWebFrameworkResponse extends BaseResponse { From e26365b9503e3fdd5667838abbecaeb8d0f5eca1 Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 30 Mar 2023 14:58:23 +0900 Subject: [PATCH 13/18] mv license --- api/license.ts | 5 +++++ api/types.ts | 13 +++---------- 2 files changed, 8 insertions(+), 10 deletions(-) create mode 100644 api/license.ts diff --git a/api/license.ts b/api/license.ts new file mode 100644 index 00000000..cac15b1e --- /dev/null +++ b/api/license.ts @@ -0,0 +1,5 @@ +export const LICENSE_CE = { + "ce-use-of-generated-code": "Public Domain", + "ce-use-of-engine-source": "Apache-2.0", + "ce-use-for-commercial": "AGPL-3.0", +}; diff --git a/api/types.ts b/api/types.ts index 2797e0ca..72960c16 100644 --- a/api/types.ts +++ b/api/types.ts @@ -2,25 +2,20 @@ import type { FrameworkConfig, VanillaFrameworkConfig, } from "@grida/builder-config"; +import { LICENSE_CE } from "./license"; export type FigmaNodeInput = | string | { url: string; version: string } | { filekey: string; node: string; version: string }; -export interface CodeRequets { +export interface CodeRequest { figma: FigmaNodeInput; framework: Partial; } export type CodeResponse = FigmaToVanillaResponse; -export const LICENSE_CE = { - "ce-use-of-generated-code": "Public Domain", - "ce-use-of-engine-source": "Apache-2.0", - "ce-use-for-commercial": "AGPL-3.0", -}; - export type ApiEngineInfo = { name: "code.grida.co/api/v1"; version: "2023.1.1"; @@ -67,9 +62,7 @@ export interface BaseWebFrameworkResponse extends BaseResponse { srcdoc: string; srcmap: D2CSourceMap; files: { - [key: string]: { - content: string; - }; + [key: string]: string; }; thumbnail: string; From 2a9407560f804648706fd9184870b96e1b215f62 Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 30 Mar 2023 14:58:30 +0900 Subject: [PATCH 14/18] update docs --- api/README.md | 2 +- api/index.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/api/README.md b/api/README.md index 03d9428c..aa2fe44c 100644 --- a/api/README.md +++ b/api/README.md @@ -31,7 +31,7 @@ client.post("code", { #### Request Body ```ts -interface CodeRequets { +interface CodeRequest { figma: FigmaNodeInput; framework: Partial; } diff --git a/api/index.ts b/api/index.ts index eea524d6..d6fcf1a5 100644 --- a/api/index.ts +++ b/api/index.ts @@ -1 +1,2 @@ export * from "./types"; +export * from "./license"; From 162d51b152624ba15b390dd6222f87efb8394cf8 Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 30 Mar 2023 14:58:53 +0900 Subject: [PATCH 15/18] update api response format --- editor/next.config.js | 1 + editor/pages/api/v1/code/index.ts | 112 +++++++++++++++++++++--------- package.json | 1 + 3 files changed, 80 insertions(+), 34 deletions(-) diff --git a/editor/next.config.js b/editor/next.config.js index 17e7557d..e18ca9de 100644 --- a/editor/next.config.js +++ b/editor/next.config.js @@ -20,6 +20,7 @@ const packages = [ // ----------------------------- // region @designto-code + "@grida/api", "@grida/code", "@designto/debugger", "@grida/builder-config", diff --git a/editor/pages/api/v1/code/index.ts b/editor/pages/api/v1/code/index.ts index ffb7f588..48d1a00f 100644 --- a/editor/pages/api/v1/code/index.ts +++ b/editor/pages/api/v1/code/index.ts @@ -1,49 +1,93 @@ import { code } from "@grida/code"; -type FigmaAccessTokenType = "at" | "pat"; +import type { CodeRequest, FigmaToVanillaResponse } from "@grida/api/types"; +import { LICENSE_CE } from "@grida/api"; +import assert from "assert"; +import { FrameworkConfig, VanillaFrameworkConfig } from "@grida/builder-config"; + +type FigmaAccessTokenType = "fat" | "fpat"; export default async function handler(req, res) { - // accept only post request - if (req.method !== "POST") { - res.status(405).json({ message: "method not allowed" }); - return; - } + try { + // accept only post request + if (req.method !== "POST") { + res.status(405).json({ message: "method not allowed" }); + return; + } - const figma_access_token: string = req.headers["x-figma-token"]; + const figma_access_token: string = req.headers["x-figma-token"]; - if (!figma_access_token) { - res.status(401).json({ - message: "No figma access token provided.", - }); - return; - } + if (!figma_access_token) { + res.status(401).json({ + message: "No figma access token provided.", + }); + return; + } - const figma_access_token_type: FigmaAccessTokenType = - figma_access_token.startsWith("figd") ? "pat" : "at"; + const figma_access_token_type: FigmaAccessTokenType = + figma_access_token.startsWith("figd") ? "fpat" : "fat"; - const { uri, framework } = req.body; - try { - const src = await code({ - uri, - framework, - auth: - figma_access_token_type === "at" - ? { - accessToken: figma_access_token, - } - : { - personalAccessToken: figma_access_token, - }, - }); + const { figma, framework } = req.body as CodeRequest; - res.status(200).json({ - src, - }); + assert(typeof figma === "string", "`body.figma` must be a string"); + + try { + const src = await code({ + uri: figma, + framework: framework as FrameworkConfig, + auth: + figma_access_token_type === "fat" + ? { + accessToken: figma_access_token, + } + : { + personalAccessToken: figma_access_token, + }, + }); + + const response: FigmaToVanillaResponse = { + figma: { + file: { + name: "", + lastModified: "", + thumbnailUrl: "", + version: "", + }, + filekey: "", + entry: "", + node: undefined, + json: "", + }, + framework: framework as VanillaFrameworkConfig, + src: "", + srcdoc: "", + srcmap: null, // TODO: + files: { + "index.html": src, + }, + thumbnail: null, // TODO: + engine: { + name: "code.grida.co/api/v1", + version: "2023.1.1", + license: "AGPL-3.0", + }, + version: 0, + license: LICENSE_CE, + warnings: [], + }; + + res.status(200).json(response); + } catch (e) { + res.status(500).json({ + message: e.message, + stacktrace: e.stack, + }); + + throw e; + } } catch (e) { res.status(500).json({ message: e.message, stacktrace: e.stack, }); - - throw e; } } diff --git a/package.json b/package.json index d79361fc..3f458a19 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "workspaces": [ "editor", "code", + "api", "editor-packages/*", "packages/*", "ui/editor-ui/packages/*" From 8e07f97b2987c3e28d9886679ad5551733d3baf5 Mon Sep 17 00:00:00 2001 From: Universe Date: Thu, 30 Mar 2023 15:22:10 +0900 Subject: [PATCH 16/18] update api response --- api/types.ts | 2 +- code/index.ts | 11 +++++--- editor/pages/api/v1/code/index.ts | 43 +++++++++++++++++++----------- editor/pages/api/v1/embed/index.ts | 2 +- 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/api/types.ts b/api/types.ts index 72960c16..c60db8c6 100644 --- a/api/types.ts +++ b/api/types.ts @@ -42,7 +42,7 @@ export type FigmaInputPong = { * the full node tree, including only essential information. like size, position, etc. */ node: object; - json: string; + json: object; }; export interface BaseFigmaInputResponse { diff --git a/code/index.ts b/code/index.ts index 91d17e06..91fd7760 100644 --- a/code/index.ts +++ b/code/index.ts @@ -31,8 +31,6 @@ export async function code({ if (res) { const { file: filekey, node } = res; - console.log(`filekey: ${filekey}`, `node: ${node}`); - // const target = await fetchTargetAsReflect({ file: filekey, @@ -68,7 +66,14 @@ export async function code({ framework.language ); - return src; + return { + src, + figma: { + filekey, + node, + }, + target, + }; } } diff --git a/editor/pages/api/v1/code/index.ts b/editor/pages/api/v1/code/index.ts index 48d1a00f..c4d26023 100644 --- a/editor/pages/api/v1/code/index.ts +++ b/editor/pages/api/v1/code/index.ts @@ -26,13 +26,13 @@ export default async function handler(req, res) { const figma_access_token_type: FigmaAccessTokenType = figma_access_token.startsWith("figd") ? "fpat" : "fat"; - const { figma, framework } = req.body as CodeRequest; + const { figma: figmaInput, framework } = req.body as CodeRequest; - assert(typeof figma === "string", "`body.figma` must be a string"); + assert(typeof figmaInput === "string", "`body.figma` must be a string"); try { - const src = await code({ - uri: figma, + const coderes = await code({ + uri: figmaInput, framework: framework as FrameworkConfig, auth: figma_access_token_type === "fat" @@ -44,22 +44,29 @@ export default async function handler(req, res) { }, }); + const { src: spchar_src, figma, target } = coderes; + + const src = replaceSpecialChars(spchar_src); + const response: FigmaToVanillaResponse = { figma: { - file: { - name: "", - lastModified: "", - thumbnailUrl: "", - version: "", - }, - filekey: "", - entry: "", - node: undefined, - json: "", + file: + // null, // TODO: + { + name: undefined, + lastModified: undefined, + thumbnailUrl: undefined, + version: undefined, + }, + + filekey: figma.filekey, + entry: figma.node, + node: target.figma, + json: target.remote, }, framework: framework as VanillaFrameworkConfig, - src: "", - srcdoc: "", + src: null, // TODO: + srcdoc: src, srcmap: null, // TODO: files: { "index.html": src, @@ -91,3 +98,7 @@ export default async function handler(req, res) { }); } } + +function replaceSpecialChars(input: string): string { + return input.replace(/\\t/g, "\t").replace(/\\n/g, "\n"); +} diff --git a/editor/pages/api/v1/embed/index.ts b/editor/pages/api/v1/embed/index.ts index e6907723..8cbfb324 100644 --- a/editor/pages/api/v1/embed/index.ts +++ b/editor/pages/api/v1/embed/index.ts @@ -17,7 +17,7 @@ export default async function handler(req: Request, res: Response) { } try { - const src = await code({ + const { src } = await code({ uri: figma as string, framework: { framework: "preview", From bb66d43785468fe907dc789fdef67fcf431483d3 Mon Sep 17 00:00:00 2001 From: Universe Date: Fri, 31 Mar 2023 21:33:30 +0900 Subject: [PATCH 17/18] update figma url node-id handling --- packages/designto-code/package.json | 4 ++-- yarn.lock | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/designto-code/package.json b/packages/designto-code/package.json index 6b3763b1..be424b43 100644 --- a/packages/designto-code/package.json +++ b/packages/designto-code/package.json @@ -18,7 +18,7 @@ "@design-sdk/figma-node-repository": "^0.0.43", "@design-sdk/figma-remote": "^0.0.43", "@design-sdk/figma-remote-types": "^0.0.43", - "@design-sdk/figma-url": "^0.0.43", + "@design-sdk/figma-url": "^0.0.46", "@design-sdk/flags": "^0.0.43", "@design-sdk/url-analysis": "^0.0.43", "@designto/flutter": "0.0.1", @@ -34,4 +34,4 @@ "lib/**/*.ts", "lib/**/*.js" ] -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 185385a0..e8067beb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1538,6 +1538,11 @@ resolved "https://registry.npmjs.org/@design-sdk/figma-url/-/figma-url-0.0.43.tgz" integrity sha512-9bH9GZ7jdLcd1RK0UKybNGoPQQ0Uvk5JI165r1Ur61hbnusHdsn3MhY/VcJUKeLeT4t7Zr7eEVKL2fyYTankdA== +"@design-sdk/figma-url@^0.0.46": + version "0.0.46" + resolved "https://registry.yarnpkg.com/@design-sdk/figma-url/-/figma-url-0.0.46.tgz#8cf8eecbb80685480822734bfa871af6e5fa0daa" + integrity sha512-9d8Og45cPxRe3Oh8wzWHhFrxZYfaoBdfP/J0OfYs2yTK7XY/vhz1GGf78aBjGdBdmaShHwfI8RHIhhV03nYKkg== + "@design-sdk/figma-utils@^0.0.25": version "0.0.25" resolved "https://registry.yarnpkg.com/@design-sdk/figma-utils/-/figma-utils-0.0.25.tgz#7b7f6632fd8689ef713b27b34a61257accc2052e" From d260001a27a16766a78c5c6d6756c58b5e82d5d6 Mon Sep 17 00:00:00 2001 From: Universe Date: Fri, 31 Mar 2023 22:17:18 +0900 Subject: [PATCH 18/18] resolve flex grow being blocked by positioned wrapper token --- .../compose-wrapped-with-positioned.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/designto-web/tokens-to-web-widget/compose-wrapped-with-positioned.ts b/packages/designto-web/tokens-to-web-widget/compose-wrapped-with-positioned.ts index 2cc495e6..5a35d9d9 100644 --- a/packages/designto-web/tokens-to-web-widget/compose-wrapped-with-positioned.ts +++ b/packages/designto-web/tokens-to-web-widget/compose-wrapped-with-positioned.ts @@ -8,10 +8,13 @@ export function compose_wrapped_with_positioned( ) { const child = child_composer(widget.child); // ------------------------------------- + // TODO: check the version history and investigate why this was added // override w & h with position provided w/h child.extendStyle({ - width: css.length(widget.width), - height: css.length(widget.height), + // unless it was cleared intentionally + width: child.width === undefined ? undefined : css.length(widget.width), + // unless it was cleared intentionally + height: child.height === undefined ? undefined : css.length(widget.height), }); // ------------------------------------- child.constraint = {