diff --git a/fixtures/webstudio-features/.webstudio/data.json b/fixtures/webstudio-features/.webstudio/data.json index f5473c7fd0ea..126e64e5e4a1 100644 --- a/fixtures/webstudio-features/.webstudio/data.json +++ b/fixtures/webstudio-features/.webstudio/data.json @@ -1,10 +1,10 @@ { "build": { - "id": "f0dfc2e7-240a-4542-ad28-a4cb68b2d9db", + "id": "043bda3f-0d77-4656-aa9c-652c1a1f272e", "projectId": "cddc1d44-af37-4cb6-a430-d300cf6f932d", - "version": 583, - "createdAt": "2025-04-14T09:45:34.257+00:00", - "updatedAt": "2025-04-14T09:45:34.257+00:00", + "version": 593, + "createdAt": "2025-05-15T22:04:05.511+00:00", + "updatedAt": "2025-05-15T22:04:05.511+00:00", "pages": { "meta": { "siteName": "KittyGuardedZone", @@ -2165,6 +2165,18 @@ "value": "center" } } + ], + [ + "U6kV-2LTnN9kR4jWfLb1c:UoTkWyaFuTYJihS3MFYK5:display:", + { + "breakpointId": "UoTkWyaFuTYJihS3MFYK5", + "styleSourceId": "U6kV-2LTnN9kR4jWfLb1c", + "property": "display", + "value": { + "type": "keyword", + "value": "block" + } + } ] ], "styleSources": [ @@ -2482,6 +2494,13 @@ "type": "local", "id": "hEVSzkOEBn_3dNyo65PAM" } + ], + [ + "U6kV-2LTnN9kR4jWfLb1c", + { + "type": "local", + "id": "U6kV-2LTnN9kR4jWfLb1c" + } ] ], "styleSourceSelections": [ @@ -2799,6 +2818,13 @@ "instanceId": "g__o13UKOkD0KImnp-sWp", "values": ["hEVSzkOEBn_3dNyo65PAM"] } + ], + [ + "Ol5bklKKxyJaS7Q3jcCfD", + { + "instanceId": "Ol5bklKKxyJaS7Q3jcCfD", + "values": ["U6kV-2LTnN9kR4jWfLb1c"] + } ] ], "props": [ @@ -2812,16 +2838,6 @@ "value": "cd939c56-bcdd-4e64-bd9c-567a9bccd3da" } ], - [ - "SYK4hpLQ9tHnESKDtPvI9", - { - "id": "SYK4hpLQ9tHnESKDtPvI9", - "instanceId": "l9AI_pShC-BH4ibxK6kNT", - "name": "href", - "type": "string", - "value": "https://github.com/" - } - ], [ "_x-dxwbTQ-XBLRuYQE9Pm", { @@ -4111,6 +4127,16 @@ "type": "boolean", "value": true } + ], + [ + "qG9NyGQuq0KVR0zvf76Er", + { + "id": "qG9NyGQuq0KVR0zvf76Er", + "instanceId": "Ol5bklKKxyJaS7Q3jcCfD", + "name": "href", + "type": "string", + "value": "https://github.com/" + } ] ], "dataSources": [ @@ -4432,7 +4458,7 @@ }, { "type": "id", - "value": "l9AI_pShC-BH4ibxK6kNT" + "value": "Ol5bklKKxyJaS7Q3jcCfD" }, { "type": "id", @@ -4508,20 +4534,6 @@ "children": [] } ], - [ - "l9AI_pShC-BH4ibxK6kNT", - { - "type": "instance", - "id": "l9AI_pShC-BH4ibxK6kNT", - "component": "Link", - "children": [ - { - "type": "text", - "value": "Click here to adore more kittens" - } - ] - } - ], [ "uKWGyE9JY3cPwY-xI9vk6", { @@ -6728,6 +6740,21 @@ } ] } + ], + [ + "Ol5bklKKxyJaS7Q3jcCfD", + { + "type": "instance", + "id": "Ol5bklKKxyJaS7Q3jcCfD", + "component": "ws:element", + "tag": "a", + "children": [ + { + "type": "text", + "value": "Click here to adore more kittens" + } + ] + } ] ], "deployment": { diff --git a/fixtures/webstudio-features/app/__generated__/$resources.sitemap.xml.ts b/fixtures/webstudio-features/app/__generated__/$resources.sitemap.xml.ts index d33e6cb8fb0f..4adf5d883e30 100644 --- a/fixtures/webstudio-features/app/__generated__/$resources.sitemap.xml.ts +++ b/fixtures/webstudio-features/app/__generated__/$resources.sitemap.xml.ts @@ -1,26 +1,26 @@ export const sitemap = [ { path: "/", - lastModified: "2025-04-14", + lastModified: "2025-05-15", }, { path: "/_route_with_symbols_", - lastModified: "2025-04-14", + lastModified: "2025-05-15", }, { path: "/form", - lastModified: "2025-04-14", + lastModified: "2025-05-15", }, { path: "/heading-with-id", - lastModified: "2025-04-14", + lastModified: "2025-05-15", }, { path: "/resources", - lastModified: "2025-04-14", + lastModified: "2025-05-15", }, { path: "/nested/nested-page", - lastModified: "2025-04-14", + lastModified: "2025-05-15", }, ]; diff --git a/fixtures/webstudio-features/app/__generated__/[_route_with_symbols_]._index.tsx b/fixtures/webstudio-features/app/__generated__/[_route_with_symbols_]._index.tsx index 9c281b2bb89a..72512f300034 100644 --- a/fixtures/webstudio-features/app/__generated__/[_route_with_symbols_]._index.tsx +++ b/fixtures/webstudio-features/app/__generated__/[_route_with_symbols_]._index.tsx @@ -8,7 +8,7 @@ import { Image as Image } from "@webstudio-is/sdk-components-react"; export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; diff --git a/fixtures/webstudio-features/app/__generated__/[animations]._index.tsx b/fixtures/webstudio-features/app/__generated__/[animations]._index.tsx index 98b20e7fd504..967cff4e83ea 100644 --- a/fixtures/webstudio-features/app/__generated__/[animations]._index.tsx +++ b/fixtures/webstudio-features/app/__generated__/[animations]._index.tsx @@ -15,7 +15,7 @@ import { export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; diff --git a/fixtures/webstudio-features/app/__generated__/[class-names]._index.tsx b/fixtures/webstudio-features/app/__generated__/[class-names]._index.tsx index 0d81948c412c..0251b4eba87e 100644 --- a/fixtures/webstudio-features/app/__generated__/[class-names]._index.tsx +++ b/fixtures/webstudio-features/app/__generated__/[class-names]._index.tsx @@ -8,7 +8,7 @@ import { Box as Box } from "@webstudio-is/sdk-components-react"; export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; diff --git a/fixtures/webstudio-features/app/__generated__/[content-block]._index.tsx b/fixtures/webstudio-features/app/__generated__/[content-block]._index.tsx index 5281a7759002..b4c83bb60bcc 100644 --- a/fixtures/webstudio-features/app/__generated__/[content-block]._index.tsx +++ b/fixtures/webstudio-features/app/__generated__/[content-block]._index.tsx @@ -12,7 +12,7 @@ import { export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; diff --git a/fixtures/webstudio-features/app/__generated__/[duration]._index.tsx b/fixtures/webstudio-features/app/__generated__/[duration]._index.tsx index f8072156dff5..09871db730b7 100644 --- a/fixtures/webstudio-features/app/__generated__/[duration]._index.tsx +++ b/fixtures/webstudio-features/app/__generated__/[duration]._index.tsx @@ -9,7 +9,7 @@ import { Heading as Heading } from "@webstudio-is/sdk-components-react"; export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; diff --git a/fixtures/webstudio-features/app/__generated__/[expressions]._index.tsx b/fixtures/webstudio-features/app/__generated__/[expressions]._index.tsx index 8aedb43c32a7..7308a5640b92 100644 --- a/fixtures/webstudio-features/app/__generated__/[expressions]._index.tsx +++ b/fixtures/webstudio-features/app/__generated__/[expressions]._index.tsx @@ -12,7 +12,7 @@ import { export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; diff --git a/fixtures/webstudio-features/app/__generated__/[form]._index.tsx b/fixtures/webstudio-features/app/__generated__/[form]._index.tsx index 9709fe9b2d67..5318e790eb3d 100644 --- a/fixtures/webstudio-features/app/__generated__/[form]._index.tsx +++ b/fixtures/webstudio-features/app/__generated__/[form]._index.tsx @@ -17,7 +17,7 @@ import { export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; diff --git a/fixtures/webstudio-features/app/__generated__/[head-tag]._index.tsx b/fixtures/webstudio-features/app/__generated__/[head-tag]._index.tsx index 6a7000811dbb..9320d5efca81 100644 --- a/fixtures/webstudio-features/app/__generated__/[head-tag]._index.tsx +++ b/fixtures/webstudio-features/app/__generated__/[head-tag]._index.tsx @@ -17,7 +17,7 @@ import { export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; diff --git a/fixtures/webstudio-features/app/__generated__/[heading-with-id]._index.tsx b/fixtures/webstudio-features/app/__generated__/[heading-with-id]._index.tsx index ac381b1d1436..5b5e3f7cfe25 100644 --- a/fixtures/webstudio-features/app/__generated__/[heading-with-id]._index.tsx +++ b/fixtures/webstudio-features/app/__generated__/[heading-with-id]._index.tsx @@ -8,7 +8,7 @@ import { Heading as Heading } from "@webstudio-is/sdk-components-react"; export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; diff --git a/fixtures/webstudio-features/app/__generated__/[nested].[nested-page]._index.tsx b/fixtures/webstudio-features/app/__generated__/[nested].[nested-page]._index.tsx index 02aaaaa3b7f2..f8c3fc682356 100644 --- a/fixtures/webstudio-features/app/__generated__/[nested].[nested-page]._index.tsx +++ b/fixtures/webstudio-features/app/__generated__/[nested].[nested-page]._index.tsx @@ -8,7 +8,7 @@ import { Heading as Heading } from "@webstudio-is/sdk-components-react"; export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; diff --git a/fixtures/webstudio-features/app/__generated__/[radix]._index.tsx b/fixtures/webstudio-features/app/__generated__/[radix]._index.tsx index f9999e091f25..4a99e3b1a539 100644 --- a/fixtures/webstudio-features/app/__generated__/[radix]._index.tsx +++ b/fixtures/webstudio-features/app/__generated__/[radix]._index.tsx @@ -19,7 +19,7 @@ import { export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; diff --git a/fixtures/webstudio-features/app/__generated__/[resources]._index.tsx b/fixtures/webstudio-features/app/__generated__/[resources]._index.tsx index 53250ff8d846..6e40d8fb3fc6 100644 --- a/fixtures/webstudio-features/app/__generated__/[resources]._index.tsx +++ b/fixtures/webstudio-features/app/__generated__/[resources]._index.tsx @@ -11,7 +11,7 @@ import { export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; diff --git a/fixtures/webstudio-features/app/__generated__/[sitemap.xml]._index.tsx b/fixtures/webstudio-features/app/__generated__/[sitemap.xml]._index.tsx index c53f64fd0d5b..06acae7bf9db 100644 --- a/fixtures/webstudio-features/app/__generated__/[sitemap.xml]._index.tsx +++ b/fixtures/webstudio-features/app/__generated__/[sitemap.xml]._index.tsx @@ -10,7 +10,7 @@ import { export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; diff --git a/fixtures/webstudio-features/app/__generated__/[text-duration]._index.tsx b/fixtures/webstudio-features/app/__generated__/[text-duration]._index.tsx index f46671b99871..0f13b7814636 100644 --- a/fixtures/webstudio-features/app/__generated__/[text-duration]._index.tsx +++ b/fixtures/webstudio-features/app/__generated__/[text-duration]._index.tsx @@ -12,7 +12,7 @@ import { Heading as Heading } from "@webstudio-is/sdk-components-react"; export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; diff --git a/fixtures/webstudio-features/app/__generated__/_index.tsx b/fixtures/webstudio-features/app/__generated__/_index.tsx index 36fa9cc5d0d9..6248c70bf485 100644 --- a/fixtures/webstudio-features/app/__generated__/_index.tsx +++ b/fixtures/webstudio-features/app/__generated__/_index.tsx @@ -6,6 +6,7 @@ import { useResource, useVariableState } from "@webstudio-is/react-sdk/runtime"; import { Body as Body, Link as Link, + Link as Link_1, } from "@webstudio-is/sdk-components-react-router"; import { Heading as Heading, @@ -17,7 +18,7 @@ import { export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d"; -export const lastPublished = "2025-04-14T09:45:34.257Z"; +export const lastPublished = "2025-05-15T22:04:05.511Z"; export const siteName = "KittyGuardedZone"; @@ -72,9 +73,9 @@ const Page = (_props: { system: any }) => { "a little kitten painted in black and white gouache with a thick brush" } - + {"Click here to adore more kittens"} - + {" or "} diff --git a/fixtures/webstudio-features/app/__generated__/index.css b/fixtures/webstudio-features/app/__generated__/index.css index 6a94668cb011..4d4b55ef0a86 100644 --- a/fixtures/webstudio-features/app/__generated__/index.css +++ b/fixtures/webstudio-features/app/__generated__/index.css @@ -8,6 +8,14 @@ white-space: pre-wrap; white-space-collapse: preserve; } + a.w-element { + box-sizing: border-box; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + outline-width: 1px; + } body.w-body { box-sizing: border-box; border-top-width: 1px; diff --git a/fixtures/webstudio-features/package.json b/fixtures/webstudio-features/package.json index 915298800832..b50c50a4c8ee 100644 --- a/fixtures/webstudio-features/package.json +++ b/fixtures/webstudio-features/package.json @@ -6,7 +6,7 @@ "dev": "react-router dev", "cli": "NODE_OPTIONS='--conditions=webstudio --import=tsx' webstudio", "fixtures:link": "pnpm cli link --link https://p-cddc1d44-af37-4cb6-a430-d300cf6f932d-dot-${BUILDER_HOST:-main.development.webstudio.is}'?authToken=1cdc6026-dd5b-4624-b89b-9bd45e9bcc3d'", - "fixtures:sync": "pnpm cli sync --buildId f0dfc2e7-240a-4542-ad28-a4cb68b2d9db && pnpm prettier --write ./.webstudio/", + "fixtures:sync": "pnpm cli sync --buildId 043bda3f-0d77-4656-aa9c-652c1a1f272e && pnpm prettier --write ./.webstudio/", "fixtures:build": "pnpm cli build --template react-router --template ./.template && pnpm prettier --write ./app/ ./package.json ./tsconfig.json" }, "private": true, diff --git a/packages/cli/src/framework-react-router.ts b/packages/cli/src/framework-react-router.ts index a956faec58be..0d007e43a246 100644 --- a/packages/cli/src/framework-react-router.ts +++ b/packages/cli/src/framework-react-router.ts @@ -4,7 +4,6 @@ import type { WsComponentMeta } from "@webstudio-is/sdk"; import { generateRemixRoute } from "@webstudio-is/react-sdk"; import * as baseComponentMetas from "@webstudio-is/sdk-components-react/metas"; import * as animationComponentMetas from "@webstudio-is/sdk-components-animation/metas"; -import * as reactRouterComponentMetas from "@webstudio-is/sdk-components-react-router/metas"; import * as radixComponentMetas from "@webstudio-is/sdk-components-react-radix/metas"; import type { Framework } from "./framework"; @@ -31,37 +30,36 @@ export const createFramework = async (): Promise => { // cleanup route templates after reading to not bloat generated code await rm(routeTemplatesDir, { recursive: true, force: true }); - const radixComponentNamespacedMetas: Record = {}; + const base = "@webstudio-is/sdk-components-react"; + const reactRouter = "@webstudio-is/sdk-components-react-router"; + const reactRadix = "@webstudio-is/sdk-components-react-radix"; + const animation = "@webstudio-is/sdk-components-animation"; + const components: Record = {}; + const metas: Record = {}; + for (const [name, meta] of Object.entries(baseComponentMetas)) { + components[name] = `${base}:${name}`; + metas[name] = meta; + } + for (const name of ["Body", "Link", "RichTextLink", "Form", "RemixForm"]) { + components[name] = `${reactRouter}:${name}`; + } for (const [name, meta] of Object.entries(radixComponentMetas)) { - const namespace = "@webstudio-is/sdk-components-react-radix"; - radixComponentNamespacedMetas[`${namespace}:${name}`] = meta; + components[`${reactRadix}:${name}`] = `${reactRadix}:${name}`; + metas[`${reactRadix}:${name}`] = meta; } - - const animationComponentNamespacedMetas: Record = {}; for (const [name, meta] of Object.entries(animationComponentMetas)) { - const namespace = "@webstudio-is/sdk-components-animation"; - animationComponentNamespacedMetas[`${namespace}:${name}`] = meta; + components[`${animation}:${name}`] = `${animation}:${name}`; + metas[`${animation}:${name}`] = meta; } return { - components: [ - { - source: "@webstudio-is/sdk-components-react", - metas: baseComponentMetas, - }, - { - source: "@webstudio-is/sdk-components-animation", - metas: animationComponentNamespacedMetas, - }, - { - source: "@webstudio-is/sdk-components-react-radix", - metas: radixComponentNamespacedMetas, - }, - { - source: "@webstudio-is/sdk-components-react-router", - metas: reactRouterComponentMetas, - }, - ], + metas, + components, + tags: { + body: `${reactRouter}:Body`, + a: `${reactRouter}:Link`, + form: `${reactRouter}:RemixForm`, + }, html: ({ pagePath }: { pagePath: string }) => [ { file: join("app", "routes", `${generateRemixRoute(pagePath)}.tsx`), diff --git a/packages/cli/src/framework-remix.ts b/packages/cli/src/framework-remix.ts index debb68cd6aa0..d03a527c2b09 100644 --- a/packages/cli/src/framework-remix.ts +++ b/packages/cli/src/framework-remix.ts @@ -4,7 +4,6 @@ import type { WsComponentMeta } from "@webstudio-is/sdk"; import { generateRemixRoute } from "@webstudio-is/react-sdk"; import * as baseComponentMetas from "@webstudio-is/sdk-components-react/metas"; import * as animationComponentMetas from "@webstudio-is/sdk-components-animation/metas"; -import * as remixComponentMetas from "@webstudio-is/sdk-components-react-remix/metas"; import * as radixComponentMetas from "@webstudio-is/sdk-components-react-radix/metas"; import type { Framework } from "./framework"; @@ -31,37 +30,36 @@ export const createFramework = async (): Promise => { // cleanup route templates after reading to not bloat generated code await rm(routeTemplatesDir, { recursive: true, force: true }); - const radixComponentNamespacedMetas: Record = {}; + const base = "@webstudio-is/sdk-components-react"; + const remix = "@webstudio-is/sdk-components-react-remix"; + const reactRadix = "@webstudio-is/sdk-components-react-radix"; + const animation = "@webstudio-is/sdk-components-animation"; + const components: Record = {}; + const metas: Record = {}; + for (const [name, meta] of Object.entries(baseComponentMetas)) { + components[name] = `${base}:${name}`; + metas[name] = meta; + } + for (const name of ["Body", "Link", "RichTextLink", "Form", "RemixForm"]) { + components[name] = `${remix}:${name}`; + } for (const [name, meta] of Object.entries(radixComponentMetas)) { - const namespace = "@webstudio-is/sdk-components-react-radix"; - radixComponentNamespacedMetas[`${namespace}:${name}`] = meta; + components[`${reactRadix}:${name}`] = `${reactRadix}:${name}`; + metas[`${reactRadix}:${name}`] = meta; } - - const animationComponentNamespacedMetas: Record = {}; for (const [name, meta] of Object.entries(animationComponentMetas)) { - const namespace = "@webstudio-is/sdk-components-animation"; - animationComponentNamespacedMetas[`${namespace}:${name}`] = meta; + components[`${animation}:${name}`] = `${animation}:${name}`; + metas[`${animation}:${name}`] = meta; } return { - components: [ - { - source: "@webstudio-is/sdk-components-react", - metas: baseComponentMetas, - }, - { - source: "@webstudio-is/sdk-components-animation", - metas: animationComponentNamespacedMetas, - }, - { - source: "@webstudio-is/sdk-components-react-radix", - metas: radixComponentNamespacedMetas, - }, - { - source: "@webstudio-is/sdk-components-react-remix", - metas: remixComponentMetas, - }, - ], + metas, + components, + tags: { + body: `${remix}:Body`, + a: `${remix}:Link`, + form: `${remix}:RemixForm`, + }, html: ({ pagePath }: { pagePath: string }) => [ { file: join("app", "routes", `${generateRemixRoute(pagePath)}.tsx`), diff --git a/packages/cli/src/framework-vike-ssg.ts b/packages/cli/src/framework-vike-ssg.ts index d9f747a0c9f8..148c59ea7be0 100644 --- a/packages/cli/src/framework-vike-ssg.ts +++ b/packages/cli/src/framework-vike-ssg.ts @@ -32,33 +32,28 @@ export const createFramework = async (): Promise => { // cleanup route templates after reading to not bloat generated code await rm(routeTemplatesDir, { recursive: true, force: true }); - const radixComponentNamespacedMetas: Record = {}; + const base = "@webstudio-is/sdk-components-react"; + const reactRadix = "@webstudio-is/sdk-components-react-radix"; + const animation = "@webstudio-is/sdk-components-animation"; + const components: Record = {}; + const metas: Record = {}; + for (const [name, meta] of Object.entries(baseComponentMetas)) { + components[name] = `${base}:${name}`; + metas[name] = meta; + } for (const [name, meta] of Object.entries(radixComponentMetas)) { - const namespace = "@webstudio-is/sdk-components-react-radix"; - radixComponentNamespacedMetas[`${namespace}:${name}`] = meta; + components[`${reactRadix}:${name}`] = `${reactRadix}:${name}`; + metas[`${reactRadix}:${name}`] = meta; } - - const animationComponentNamespacedMetas: Record = {}; for (const [name, meta] of Object.entries(animationComponentMetas)) { - const namespace = "@webstudio-is/sdk-components-animation"; - animationComponentNamespacedMetas[`${namespace}:${name}`] = meta; + components[`${animation}:${name}`] = `${animation}:${name}`; + metas[`${animation}:${name}`] = meta; } return { - components: [ - { - source: "@webstudio-is/sdk-components-react", - metas: baseComponentMetas, - }, - { - source: "@webstudio-is/sdk-components-animation", - metas: animationComponentNamespacedMetas, - }, - { - source: "@webstudio-is/sdk-components-react-radix", - metas: radixComponentNamespacedMetas, - }, - ], + metas, + components, + tags: {}, html: ({ pagePath }: { pagePath: string }) => { // ignore dynamic pages in static export if (isPathnamePattern(pagePath)) { diff --git a/packages/cli/src/framework.ts b/packages/cli/src/framework.ts index a8d89c0a7517..8871d519d840 100644 --- a/packages/cli/src/framework.ts +++ b/packages/cli/src/framework.ts @@ -1,17 +1,17 @@ import type { WsComponentMeta } from "@webstudio-is/sdk"; -type FrameworkComponentEntry = { - source: string; - metas: Record; -}; - type FrameworkTemplateEntry = { file: string; template: string; }; export type Framework = { - components: FrameworkComponentEntry[]; + // instance.component: WsComponentMeta + metas: Record; + // instance.component: "importSource:importSpecifier" + components: Record; + // instance.tag: "importSource:importSpecifier" + tags: Record; html: (params: { pagePath: string }) => FrameworkTemplateEntry[]; xml: (params: { pagePath: string }) => FrameworkTemplateEntry[]; redirect: (params: { pagePath: string }) => FrameworkTemplateEntry[]; diff --git a/packages/cli/src/prebuild.ts b/packages/cli/src/prebuild.ts index a91a1efbfd5b..29f777cc52d8 100644 --- a/packages/cli/src/prebuild.ts +++ b/packages/cli/src/prebuild.ts @@ -36,7 +36,6 @@ import { createScope, findTreeInstanceIds, getPagePath, - parseComponentName, generateResources, generatePageMeta, getStaticSiteMapXml, @@ -46,6 +45,7 @@ import { SYSTEM_VARIABLE_ID, generateCss, ROOT_INSTANCE_ID, + elementComponent, } from "@webstudio-is/sdk"; import type { Data } from "@webstudio-is/http-client"; import { LOCAL_DATA_FILE } from "./config"; @@ -285,16 +285,6 @@ export const prebuild = async (options: { ); } - // collect all possible component metas - const metas = new Map(); - const componentSources = new Map(); - for (const entry of framework.components) { - for (const [componentName, meta] of Object.entries(entry.metas)) { - metas.set(componentName, meta); - componentSources.set(componentName, entry.source); - } - } - const usedMetas = new Map( Object.entries(coreMetas) ); @@ -325,7 +315,7 @@ export const prebuild = async (options: { for (const [_instanceId, instance] of siteData.build.instances) { if (pageInstanceSet.has(instance.id)) { instances.push([instance.id, instance]); - const meta = metas.get(instance.component); + const meta = framework.metas[instance.component]; if (meta) { usedMetas.set(instance.component, meta); } @@ -518,38 +508,36 @@ export const prebuild = async (options: { } } - const pageComponents = new Set(); + // generate component imports + // Map> + const imports = new Map>(); for (const instance of instances.values()) { - pageComponents.add(instance.component); - } - const namespaces = new Map< - string, - Set<[shortName: string, componentName: string]> - >(); - for (const component of pageComponents) { - const namespace = componentSources.get(component); - if (namespace === undefined) { + let descriptor = framework.components[instance.component]; + let id = instance.component; + if (instance.component === elementComponent && instance.tag) { + descriptor = framework.tags[instance.tag]; + id = descriptor; + } + if (descriptor === undefined) { continue; } - if (namespaces.has(namespace) === false) { - namespaces.set( - namespace, - new Set<[shortName: string, componentName: string]>() - ); + const [importSource, importSpecifier] = descriptor.split(":"); + let specifiers = imports.get(importSource); + if (specifiers === undefined) { + specifiers = new Map(); + imports.set(importSource, specifiers); } - const [_namespace, shortName] = parseComponentName(component); - namespaces.get(namespace)?.add([shortName, component]); + specifiers.set(id, importSpecifier); } - - let componentImports = ""; - for (const [namespace, componentsSet] of namespaces.entries()) { - const specifiers = Array.from(componentsSet) + let importsString = ""; + for (const [importSource, specifiers] of imports) { + const specifiersString = Array.from(specifiers) .map( - ([shortName, component]) => - `${shortName} as ${scope.getName(component, shortName)}` + ([id, importSpecifier]) => + `${importSpecifier} as ${scope.getName(id, importSpecifier)}` ) .join(", "); - componentImports += `import { ${specifiers} } from "${namespace}";\n`; + importsString += `import { ${specifiersString} } from "${importSource}";\n`; } const pageFontAssets = fontAssetsByPage[page.id]; @@ -588,6 +576,7 @@ export const prebuild = async (options: { dataSources, classesMap: classes, metas: usedMetas, + tagsOverrides: framework.tags, }); const projectMeta = siteData.build.pages.meta; @@ -612,7 +601,7 @@ export const prebuild = async (options: { import { Fragment, useState } from "react"; import { useResource, useVariableState } from "@webstudio-is/react-sdk/runtime"; - ${componentImports} + ${importsString} export const projectId = "${siteData.build.projectId}"; diff --git a/packages/react-sdk/src/component-generator.test.tsx b/packages/react-sdk/src/component-generator.test.tsx index 798cd9310fdd..8f1520e4190f 100644 --- a/packages/react-sdk/src/component-generator.test.tsx +++ b/packages/react-sdk/src/component-generator.test.tsx @@ -1518,3 +1518,37 @@ test("ignore props similar to standard attributes on react components without ta ) ); }); + +test("overrides some element tags with provided components", () => { + expect( + generateWebstudioComponent({ + classesMap: new Map(), + scope: createScope(), + name: "Page", + rootInstanceId: "bodyId", + parameters: [], + metas: new Map([["HeadSlot", { icon: "" }]]), + tagsOverrides: { + body: "namespace:Body", + a: "namespace:Link", + }, + ...renderData( + + + + + ), + }) + ).toEqual( + validateJSX( + clear(` + const Page = () => { + return + +
+ + } + `) + ) + ); +}); diff --git a/packages/react-sdk/src/component-generator.ts b/packages/react-sdk/src/component-generator.ts index a2c009990f18..aa62450d6e3a 100644 --- a/packages/react-sdk/src/component-generator.ts +++ b/packages/react-sdk/src/component-generator.ts @@ -145,6 +145,7 @@ export const generateJsxElement = ({ context = "jsx", scope, metas, + tagsOverrides, instance, props, dataSources, @@ -156,6 +157,10 @@ export const generateJsxElement = ({ context?: "expression" | "jsx"; scope: Scope; metas: Map; + /** + * Record + */ + tagsOverrides?: Record; instance: Instance; props: Props; dataSources: DataSources; @@ -280,18 +285,20 @@ export const generateJsxElement = ({ generatedElement += `)}\n`; } else if (instance.component === blockComponent) { generatedElement += children; - } else if (instance.component === elementComponent) { - const tagName = instance.tag ?? "div"; - if (instance.children.length === 0) { - generatedElement += `<${tagName}${generatedProps} />\n`; + } else { + let componentVariable; + if (instance.component === elementComponent) { + componentVariable = instance.tag ?? "div"; + // replace html tag with component if available + const componentDescriptor = tagsOverrides?.[componentVariable]; + if (componentDescriptor !== undefined) { + const [_importSource, importSpecifier] = componentDescriptor.split(":"); + componentVariable = scope.getName(componentDescriptor, importSpecifier); + } } else { - generatedElement += `<${tagName}${generatedProps}>\n`; - generatedElement += children; - generatedElement += `\n`; + const [_namespace, shortName] = parseComponentName(instance.component); + componentVariable = scope.getName(instance.component, shortName); } - } else { - const [_namespace, shortName] = parseComponentName(instance.component); - const componentVariable = scope.getName(instance.component, shortName); if (instance.children.length === 0) { generatedElement += `<${componentVariable}${generatedProps} />\n`; } else { @@ -335,6 +342,7 @@ export const generateJsxElement = ({ export const generateJsxChildren = ({ scope, metas, + tagsOverrides, children, instances, props, @@ -346,6 +354,8 @@ export const generateJsxChildren = ({ }: { scope: Scope; metas: Map; + // Record + tagsOverrides?: Record; children: Instance["children"]; instances: Instances; props: Props; @@ -389,6 +399,7 @@ export const generateJsxChildren = ({ context: "jsx", scope, metas, + tagsOverrides, instance, props, dataSources, @@ -399,6 +410,7 @@ export const generateJsxChildren = ({ classesMap, scope, metas, + tagsOverrides, children: instance.children, instances, props, @@ -424,6 +436,7 @@ export const generateWebstudioComponent = ({ props, dataSources, metas, + tagsOverrides, classesMap, }: { scope: Scope; @@ -435,6 +448,10 @@ export const generateWebstudioComponent = ({ dataSources: DataSources; classesMap: Map>; metas: Map; + /** + * Record + */ + tagsOverrides?: Record; }) => { const instance = instances.get(rootInstanceId); const indexesWithinAncestors = getIndexesWithinAncestors(metas, instances, [ @@ -449,6 +466,7 @@ export const generateWebstudioComponent = ({ context: "expression", scope, metas, + tagsOverrides, instance, props, dataSources, @@ -458,6 +476,7 @@ export const generateWebstudioComponent = ({ children: generateJsxChildren({ scope, metas, + tagsOverrides, children: instance.children, instances, props, diff --git a/packages/sdk-components-react-remix/package.json b/packages/sdk-components-react-remix/package.json index 6932a7ba0ae0..21335deab7f5 100644 --- a/packages/sdk-components-react-remix/package.json +++ b/packages/sdk-components-react-remix/package.json @@ -17,20 +17,10 @@ "webstudio": "./src/components.ts", "types": "./lib/types/components.d.ts", "import": "./lib/components.js" - }, - "./metas": { - "webstudio": "./src/metas.ts", - "types": "./lib/types/metas.d.ts", - "import": "./lib/metas.js" - }, - "./props": { - "webstudio": "./src/props.ts", - "types": "./lib/types/props.d.ts", - "import": "./lib/props.js" } }, "scripts": { - "build": "vite build --config ../../vite.sdk-components.config.ts", + "build": "rm -rf lib && esbuild src/components.ts --outdir=lib --bundle --format=esm --packages=external", "dts": "tsc --project tsconfig.dts.json", "typecheck": "tsc" }, diff --git a/packages/sdk-components-react-remix/src/hooks.ts b/packages/sdk-components-react-remix/src/hooks.ts deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/packages/sdk-components-react-remix/src/metas.ts b/packages/sdk-components-react-remix/src/metas.ts deleted file mode 100644 index 4dee41be644c..000000000000 --- a/packages/sdk-components-react-remix/src/metas.ts +++ /dev/null @@ -1,9 +0,0 @@ -// this lets CLI detect which components are overriden -// without importing components runtime -export { - Body, - Link, - RichTextLink, - Form, - RemixForm, -} from "@webstudio-is/sdk-components-react/metas"; diff --git a/packages/sdk-components-react-remix/src/remix-form.tsx b/packages/sdk-components-react-remix/src/remix-form.tsx index 214834a498fc..0dead67cfea7 100644 --- a/packages/sdk-components-react-remix/src/remix-form.tsx +++ b/packages/sdk-components-react-remix/src/remix-form.tsx @@ -9,10 +9,13 @@ export const RemixForm = forwardRef< Pick & { // Remix's default behavior includes method values in both uppercase and lowercase, // resulting in our UI displaying a list that encompasses both variants. - method?: Lowercase>; + method?: Lowercase> | "dialog"; action?: string; } ->(({ action, ...props }, ref) => { +>(({ action, method, ...props }, ref) => { + if (method === "dialog") { + return
; + } // remix casts action to relative url if ( action === undefined || @@ -22,6 +25,7 @@ export const RemixForm = forwardRef< return ( & { // Remix's default behavior includes method values in both uppercase and lowercase, // resulting in our UI displaying a list that encompasses both variants. - method?: Lowercase>; + method?: Lowercase> | "dialog"; action?: string; } ->(({ action, ...props }, ref) => { +>(({ action, method, ...props }, ref) => { + if (method === "dialog") { + return ; + } // remix casts action to relative url if ( action === undefined || @@ -22,6 +25,7 @@ export const RemixForm = forwardRef< return (