diff --git a/apps/builder/app/builder/features/sidebar-left/panels/components/insert.ts b/apps/builder/app/builder/features/sidebar-left/panels/components/insert.ts index c24579038879..77adef6e6657 100644 --- a/apps/builder/app/builder/features/sidebar-left/panels/components/insert.ts +++ b/apps/builder/app/builder/features/sidebar-left/panels/components/insert.ts @@ -1,11 +1,11 @@ -import { type WsComponentMeta } from "@webstudio-is/react-sdk"; +import { ROOT_INSTANCE_ID } from "@webstudio-is/sdk"; +import type { WsComponentMeta } from "@webstudio-is/react-sdk"; import { toast } from "@webstudio-is/design-system"; import { $instances, $registeredComponentMetas, $selectedInstanceSelector, $selectedPage, - ROOT_INSTANCE_ID, } from "~/shared/nano-states"; import { computeInstancesConstraints, diff --git a/apps/builder/app/builder/features/sidebar-left/panels/navigator/navigator-tree.tsx b/apps/builder/app/builder/features/sidebar-left/panels/navigator/navigator-tree.tsx index 83a7dd5fe056..600193835a7c 100644 --- a/apps/builder/app/builder/features/sidebar-left/panels/navigator/navigator-tree.tsx +++ b/apps/builder/app/builder/features/sidebar-left/panels/navigator/navigator-tree.tsx @@ -25,7 +25,7 @@ import { showAttribute, WsComponentMeta, } from "@webstudio-is/react-sdk"; -import type { Instance } from "@webstudio-is/sdk"; +import { ROOT_INSTANCE_ID, type Instance } from "@webstudio-is/sdk"; import { EyeconClosedIcon, EyeconOpenIcon } from "@webstudio-is/icons"; import { $dragAndDropState, @@ -39,7 +39,6 @@ import { $selectedInstanceSelector, $selectedPage, getIndexedInstanceId, - ROOT_INSTANCE_ID, } from "~/shared/nano-states"; import type { InstanceSelector } from "~/shared/tree-utils"; import { serverSyncStore } from "~/shared/sync"; diff --git a/apps/builder/app/builder/features/style-panel/shared/model.tsx b/apps/builder/app/builder/features/style-panel/shared/model.tsx index 1d64024ea308..76c112d6fd5d 100644 --- a/apps/builder/app/builder/features/style-panel/shared/model.tsx +++ b/apps/builder/app/builder/features/style-panel/shared/model.tsx @@ -7,7 +7,13 @@ import { type StyleProperty, type StyleValue, } from "@webstudio-is/css-engine"; -import type { Breakpoint, Instance, StyleDecl } from "@webstudio-is/sdk"; +import { + ROOT_INSTANCE_ID, + type Breakpoint, + type Instance, + type StyleDecl, +} from "@webstudio-is/sdk"; +import { rootComponent } from "@webstudio-is/react-sdk"; import { $breakpoints, $instances, @@ -19,7 +25,6 @@ import { $selectedOrLastStyleSourceSelector, $styles, $styleSourceSelections, - ROOT_INSTANCE_ID, } from "~/shared/nano-states"; import { getComputedStyleDecl, @@ -49,7 +54,9 @@ const $presetStyles = computed($registeredComponentMetas, (metas) => { const $instanceComponents = computed( [$selectedInstanceSelector, $instances], (instanceSelector, instances) => { - const instanceComponents = new Map(); + const instanceComponents = new Map([ + [ROOT_INSTANCE_ID, rootComponent], + ]); if (instanceSelector === undefined) { return instanceComponents; } diff --git a/apps/builder/app/builder/features/style-panel/shared/style-info.test.ts b/apps/builder/app/builder/features/style-panel/shared/style-info.test.ts index 11b0eaca6220..6b599766d475 100644 --- a/apps/builder/app/builder/features/style-panel/shared/style-info.test.ts +++ b/apps/builder/app/builder/features/style-panel/shared/style-info.test.ts @@ -233,17 +233,6 @@ test("compute inherited styles", () => { "value": "antialiased", }, }, - "fontFamily": { - "instanceId": "1", - "value": { - "type": "fontFamily", - "value": [ - "Arial", - "Roboto", - "sans-serif", - ], - }, - }, "fontSize": { "instanceId": "1", "styleSourceId": "styleSourceId1", @@ -261,14 +250,6 @@ test("compute inherited styles", () => { "value": "600", }, }, - "lineHeight": { - "instanceId": "1", - "value": { - "type": "unit", - "unit": "number", - "value": 1.2, - }, - }, } `); }); diff --git a/apps/builder/app/canvas/instance-selected.ts b/apps/builder/app/canvas/instance-selected.ts index 6e30073d9db5..b44508422fd6 100644 --- a/apps/builder/app/canvas/instance-selected.ts +++ b/apps/builder/app/canvas/instance-selected.ts @@ -1,4 +1,4 @@ -import type { Instance } from "@webstudio-is/sdk"; +import { ROOT_INSTANCE_ID, type Instance } from "@webstudio-is/sdk"; import { idAttribute, selectorIdAttribute } from "@webstudio-is/react-sdk"; import { subscribeWindowResize } from "~/shared/dom-hooks"; import { @@ -14,7 +14,6 @@ import { $styles, $selectedInstanceStates, $styleSourceSelections, - ROOT_INSTANCE_ID, } from "~/shared/nano-states"; import htmlTags, { type HtmlTags } from "html-tags"; import { diff --git a/apps/builder/app/canvas/shared/styles.ts b/apps/builder/app/canvas/shared/styles.ts index ae672a6e6262..53a61369317f 100644 --- a/apps/builder/app/canvas/shared/styles.ts +++ b/apps/builder/app/canvas/shared/styles.ts @@ -3,6 +3,7 @@ import { computed } from "nanostores"; import { useStore } from "@nanostores/react"; import { Instance, + ROOT_INSTANCE_ID, getStyleDeclKey, type StyleDecl, type StyleSourceSelection, @@ -14,6 +15,7 @@ import { createImageValueTransformer, descendantComponent, type Params, + rootComponent, } from "@webstudio-is/react-sdk"; import { type VarValue, @@ -32,7 +34,6 @@ import { $selectedStyleState, $styleSourceSelections, $styles, - ROOT_INSTANCE_ID, } from "~/shared/nano-states"; import { setDifference } from "~/shared/shim"; import { $ephemeralStyles, $params } from "../stores"; @@ -330,9 +331,11 @@ export const GlobalStyles = ({ params }: { params: Params }) => { presetSheet.addMediaRule("presets"); for (const [component, meta] of metas) { for (const [tag, styles] of Object.entries(meta.presetStyle ?? {})) { - const rule = presetSheet.addNestingRule( - `${tag}:where([data-ws-component="${component}"])` - ); + const selector = + component === rootComponent + ? ":root" + : `${tag}:where([data-ws-component="${component}"])`; + const rule = presetSheet.addNestingRule(selector); for (const declaration of styles) { rule.setDeclaration({ breakpoint: "presets", diff --git a/apps/builder/app/shared/instance-utils.ts b/apps/builder/app/shared/instance-utils.ts index 853e68cfb7ba..f5f146792278 100644 --- a/apps/builder/app/shared/instance-utils.ts +++ b/apps/builder/app/shared/instance-utils.ts @@ -24,6 +24,7 @@ import { encodeDataSourceVariable, transpileExpression, getExpressionIdentifiers, + ROOT_INSTANCE_ID, } from "@webstudio-is/sdk"; import { type WsComponentMeta, @@ -46,7 +47,6 @@ import { $pages, $resources, $selectedPage, - ROOT_INSTANCE_ID, } from "./nano-states"; import { type DroppableTarget, diff --git a/apps/builder/app/shared/nano-states/instances.ts b/apps/builder/app/shared/nano-states/instances.ts index 617800458925..edfca27b5791 100644 --- a/apps/builder/app/shared/nano-states/instances.ts +++ b/apps/builder/app/shared/nano-states/instances.ts @@ -1,5 +1,5 @@ import { atom, computed } from "nanostores"; -import type { Instances } from "@webstudio-is/sdk"; +import { ROOT_INSTANCE_ID, type Instances } from "@webstudio-is/sdk"; import type { InstanceSelector } from "../tree-utils"; import { $selectedPage } from "./pages"; import { rootComponent } from "@webstudio-is/react-sdk"; @@ -20,8 +20,6 @@ export const $textEditingInstanceSelector = atom< export const $instances = atom(new Map()); -export const ROOT_INSTANCE_ID = ":root"; - export const $virtualInstances = computed($selectedPage, (selectedPage) => { const virtualInstances: Instances = new Map(); if (selectedPage) { diff --git a/apps/builder/package.json b/apps/builder/package.json index dbd40fa39a95..82f761865aa5 100644 --- a/apps/builder/package.json +++ b/apps/builder/package.json @@ -112,7 +112,7 @@ "slugify": "^1.6.6", "strip-indent": "^4.0.0", "tiny-invariant": "^1.3.3", - "title-case": "^4.3.1", + "title-case": "^4.3.2", "ultraflag": "^0.1.0", "untruncate-json": "^0.0.1", "urlpattern-polyfill": "^9.0.0", diff --git a/fixtures/ssg-netlify-by-project-id/app/__generated__/index.css b/fixtures/ssg-netlify-by-project-id/app/__generated__/index.css index 25474bc937f2..d2d47cf89380 100644 --- a/fixtures/ssg-netlify-by-project-id/app/__generated__/index.css +++ b/fixtures/ssg-netlify-by-project-id/app/__generated__/index.css @@ -1,13 +1,12 @@ -html { - margin: 0; - display: grid; - min-height: 100%; -} @media all { - :where(body.w-body) { + :root { + display: grid; + min-height: 100%; font-family: Arial, Roboto, sans-serif; font-size: 16px; line-height: 1.2; + } + :where(body.w-body) { box-sizing: border-box; border-top-width: 1px; border-right-width: 1px; diff --git a/fixtures/ssg/app/__generated__/index.css b/fixtures/ssg/app/__generated__/index.css index 20fa46db3e9c..ed250ec6c9cf 100644 --- a/fixtures/ssg/app/__generated__/index.css +++ b/fixtures/ssg/app/__generated__/index.css @@ -1,13 +1,12 @@ -html { - margin: 0; - display: grid; - min-height: 100%; -} @media all { - :where(body.w-body) { + :root { + display: grid; + min-height: 100%; font-family: Arial, Roboto, sans-serif; font-size: 16px; line-height: 1.2; + } + :where(body.w-body) { box-sizing: border-box; border-top-width: 1px; border-right-width: 1px; diff --git a/fixtures/webstudio-cloudflare-template/app/__generated__/index.css b/fixtures/webstudio-cloudflare-template/app/__generated__/index.css index 20fa46db3e9c..ed250ec6c9cf 100644 --- a/fixtures/webstudio-cloudflare-template/app/__generated__/index.css +++ b/fixtures/webstudio-cloudflare-template/app/__generated__/index.css @@ -1,13 +1,12 @@ -html { - margin: 0; - display: grid; - min-height: 100%; -} @media all { - :where(body.w-body) { + :root { + display: grid; + min-height: 100%; font-family: Arial, Roboto, sans-serif; font-size: 16px; line-height: 1.2; + } + :where(body.w-body) { box-sizing: border-box; border-top-width: 1px; border-right-width: 1px; diff --git a/fixtures/webstudio-custom-template/app/__generated__/index.css b/fixtures/webstudio-custom-template/app/__generated__/index.css index 263caf5acea9..c69c5fc73136 100644 --- a/fixtures/webstudio-custom-template/app/__generated__/index.css +++ b/fixtures/webstudio-custom-template/app/__generated__/index.css @@ -6,16 +6,15 @@ src: url("/custom-folder/CormorantGaramond-Medium_-nWJ-OtHncaW9xDHQ9hSA_CBl88Oo59QKH_z9pCWva2.woff2") format("woff2"); } -html { - margin: 0; - display: grid; - min-height: 100%; -} @media all { - :where(body.w-body) { + :root { + display: grid; + min-height: 100%; font-family: Arial, Roboto, sans-serif; font-size: 16px; line-height: 1.2; + } + :where(body.w-body) { box-sizing: border-box; border-top-width: 1px; border-right-width: 1px; diff --git a/fixtures/webstudio-remix-netlify-edge-functions/app/__generated__/index.css b/fixtures/webstudio-remix-netlify-edge-functions/app/__generated__/index.css index 20fa46db3e9c..ed250ec6c9cf 100644 --- a/fixtures/webstudio-remix-netlify-edge-functions/app/__generated__/index.css +++ b/fixtures/webstudio-remix-netlify-edge-functions/app/__generated__/index.css @@ -1,13 +1,12 @@ -html { - margin: 0; - display: grid; - min-height: 100%; -} @media all { - :where(body.w-body) { + :root { + display: grid; + min-height: 100%; font-family: Arial, Roboto, sans-serif; font-size: 16px; line-height: 1.2; + } + :where(body.w-body) { box-sizing: border-box; border-top-width: 1px; border-right-width: 1px; diff --git a/fixtures/webstudio-remix-netlify-functions/app/__generated__/index.css b/fixtures/webstudio-remix-netlify-functions/app/__generated__/index.css index 20fa46db3e9c..ed250ec6c9cf 100644 --- a/fixtures/webstudio-remix-netlify-functions/app/__generated__/index.css +++ b/fixtures/webstudio-remix-netlify-functions/app/__generated__/index.css @@ -1,13 +1,12 @@ -html { - margin: 0; - display: grid; - min-height: 100%; -} @media all { - :where(body.w-body) { + :root { + display: grid; + min-height: 100%; font-family: Arial, Roboto, sans-serif; font-size: 16px; line-height: 1.2; + } + :where(body.w-body) { box-sizing: border-box; border-top-width: 1px; border-right-width: 1px; diff --git a/fixtures/webstudio-remix-vercel/app/__generated__/index.css b/fixtures/webstudio-remix-vercel/app/__generated__/index.css index eef654c3a079..4b2a3a1dab6b 100644 --- a/fixtures/webstudio-remix-vercel/app/__generated__/index.css +++ b/fixtures/webstudio-remix-vercel/app/__generated__/index.css @@ -1,13 +1,12 @@ -html { - margin: 0; - display: grid; - min-height: 100%; -} @media all { - :where(body.w-body) { + :root { + display: grid; + min-height: 100%; font-family: Arial, Roboto, sans-serif; font-size: 16px; line-height: 1.2; + } + :where(body.w-body) { box-sizing: border-box; border-top-width: 1px; border-right-width: 1px; diff --git a/packages/cli/src/prebuild.ts b/packages/cli/src/prebuild.ts index 815baf721c80..aebc93827ea4 100644 --- a/packages/cli/src/prebuild.ts +++ b/packages/cli/src/prebuild.ts @@ -25,6 +25,7 @@ import { generateRemixRoute, generateRemixParams, isCoreComponent, + coreMetas, } from "@webstudio-is/react-sdk"; import type { Instance, @@ -294,7 +295,9 @@ export const prebuild = async (options: { } } - const projectMetas = new Map(); + const projectMetas = new Map( + Object.entries(coreMetas) + ); const componentsByPage: ComponentsByPage = {}; const siteDataByPage: SiteDataByPage = {}; const fontAssetsByPage: Record = {}; diff --git a/packages/css-engine/package.json b/packages/css-engine/package.json index ae1ab3d8a329..0a6574a122ec 100644 --- a/packages/css-engine/package.json +++ b/packages/css-engine/package.json @@ -12,7 +12,7 @@ "test": "NODE_OPTIONS=--experimental-vm-modules jest" }, "dependencies": { - "@emotion/hash": "^0.9.1", + "@emotion/hash": "^0.9.2", "@webstudio-is/error-utils": "workspace:*", "@webstudio-is/fonts": "workspace:*", "zod": "^3.22.4" diff --git a/packages/css-engine/src/core/atomic.ts b/packages/css-engine/src/core/atomic.ts index 6d6448ad99f8..1233b4cbae5f 100644 --- a/packages/css-engine/src/core/atomic.ts +++ b/packages/css-engine/src/core/atomic.ts @@ -4,7 +4,8 @@ import { NestingRule } from "./rules"; import { toValue, type TransformValue } from "./to-value"; type Options = { - getKey: (rule: NestingRule) => string; + /** in case of undefined the rule will not be split into atomics */ + getKey: (rule: NestingRule) => string | undefined; transformValue?: TransformValue; classes?: Map; }; @@ -16,6 +17,10 @@ export const generateAtomic = (sheet: StyleSheet, options: Options) => { for (const rule of sheet.nestingRules.values()) { const descendantSuffix = rule.getDescendantSuffix(); const groupKey = getKey(rule); + if (groupKey === undefined) { + atomicRules.set(rule.getSelector(), rule); + continue; + } // a few rules can be in the same group // when rule have descendant suffix let classList = classes.get(groupKey); diff --git a/packages/react-sdk/package.json b/packages/react-sdk/package.json index 8eb945491868..531e8c16791a 100644 --- a/packages/react-sdk/package.json +++ b/packages/react-sdk/package.json @@ -38,7 +38,7 @@ "change-case": "^5.4.4", "html-tags": "^4.0.0", "nanoid": "^5.0.1", - "title-case": "^4.3.1" + "title-case": "^4.3.2" }, "exports": { ".": { diff --git a/packages/react-sdk/src/core-components.ts b/packages/react-sdk/src/core-components.ts index 56d3d0591f07..d96980758923 100644 --- a/packages/react-sdk/src/core-components.ts +++ b/packages/react-sdk/src/core-components.ts @@ -3,6 +3,7 @@ import { PaintBrushIcon, EmbedIcon, } from "@webstudio-is/icons/svg"; +import { html } from "@webstudio-is/sdk/normalize.css"; import type { WsComponentMeta, WsComponentPropsMeta, @@ -15,6 +16,9 @@ const rootMeta: WsComponentMeta = { type: "container", label: "Global Root", icon: EmbedIcon, + presetStyle: { + html, + }, }; const rootPropsMeta: WsComponentPropsMeta = { diff --git a/packages/react-sdk/src/css/css.test.tsx b/packages/react-sdk/src/css/css.test.tsx index fdf5bc0ace8d..ca809e7b1606 100644 --- a/packages/react-sdk/src/css/css.test.tsx +++ b/packages/react-sdk/src/css/css.test.tsx @@ -1,7 +1,7 @@ import { expect, test } from "@jest/globals"; import type { Breakpoint } from "@webstudio-is/sdk"; import { generateCss, type CssConfig } from "./css"; -import { descendantComponent } from "../core-components"; +import { descendantComponent, rootComponent } from "../core-components"; import { $, renderJsx } from "@webstudio-is/sdk/testing"; const toMap = (list: T[]) => @@ -53,7 +53,7 @@ test("generate css for one instance with two tokens", () => { assetBaseUrl: "", }); expect(cssText).toMatchInlineSnapshot(` -"html {margin: 0; display: grid; min-height: 100%} +" @media all { .w-box { color: red @@ -61,7 +61,7 @@ test("generate css for one instance with two tokens", () => { }" `); expect(atomicCssText).toMatchInlineSnapshot(` -"html {margin: 0; display: grid; min-height: 100%} +" @media all { .cawkhls { color: red @@ -133,7 +133,7 @@ test("generate descendant selector", () => { assetBaseUrl: "", }); expect(cssText).toMatchInlineSnapshot(` -"html {margin: 0; display: grid; min-height: 100%} +" @media all { .w-body { color: blue @@ -150,7 +150,7 @@ test("generate descendant selector", () => { }" `); expect(atomicCssText).toMatchInlineSnapshot(` -"html {margin: 0; display: grid; min-height: 100%} +" @media all { .c17hlgoh { color: blue @@ -212,8 +212,7 @@ test("generate component presets with multiple tags", () => { assetBaseUrl: "", }); expect(cssText).toMatchInlineSnapshot(` -"html {margin: 0; display: grid; min-height: 100%} -@media all { +"@media all { :where(div.w-list-item) { display: block } @@ -287,8 +286,7 @@ test("deduplicate component presets for similarly named components", () => { assetBaseUrl: "", }); expect(cssText).toMatchInlineSnapshot(` -"html {margin: 0; display: grid; min-height: 100%} -@media all { +"@media all { :where(div.w-list-item) { display: block } @@ -374,8 +372,7 @@ test("expose preset classes to instances", () => { assetBaseUrl: "", }); expect(atomicCssText).toMatchInlineSnapshot(` -"html {margin: 0; display: grid; min-height: 100%} -@media all { +"@media all { :where(div.w-body) { display: block } @@ -488,8 +485,7 @@ test("generate classes with instance and meta label", () => { assetBaseUrl: "", }); expect(cssText).toMatchInlineSnapshot(` -"html {margin: 0; display: grid; min-height: 100%} -@media all { +"@media all { :where(div.w-body-meta-label) { display: block } @@ -519,3 +515,85 @@ Map { } `); }); + +test("generate :root preset and user styles", () => { + const { cssText, atomicCssText, classes, atomicClasses } = generateAllCss({ + assets: new Map(), + ...renderJsx( + <$.Body ws:id="body"> + <$.Box ws:id="box"> + + ), + breakpoints: toMap([{ id: "base", label: "" }]), + styleSourceSelections: new Map([ + [":root", { instanceId: ":root", values: ["local"] }], + ]), + styles: new Map([ + [ + "local:base:color", + { + styleSourceId: "local", + breakpointId: "base", + property: "color", + value: { type: "keyword", value: "blue" }, + }, + ], + [ + "local:base:fontSize", + { + styleSourceId: "local", + breakpointId: "base", + property: "fontSize", + value: { type: "keyword", value: "medium" }, + }, + ], + ]), + componentMetas: new Map([ + [ + rootComponent, + { + type: "container", + icon: "", + label: "Global Root", + presetStyle: { + html: [ + { + property: "display", + value: { type: "keyword", value: "grid" }, + }, + ], + }, + }, + ], + ]), + assetBaseUrl: "", + }); + expect(cssText).toMatchInlineSnapshot(` +"@media all { + :root { + display: grid + } +} +@media all { + :root { + color: blue; + font-size: medium + } +}" +`); + expect(classes).toEqual(new Map()); + expect(atomicCssText).toMatchInlineSnapshot(` +"@media all { + :root { + display: grid + } +} +@media all { + :root { + color: blue; + font-size: medium + } +}" +`); + expect(atomicClasses).toEqual(new Map()); +}); diff --git a/packages/react-sdk/src/css/css.ts b/packages/react-sdk/src/css/css.ts index a223a64bb09d..6821fa50d6a7 100644 --- a/packages/react-sdk/src/css/css.ts +++ b/packages/react-sdk/src/css/css.ts @@ -5,6 +5,7 @@ import { type TransformValue, } from "@webstudio-is/css-engine"; import { + ROOT_INSTANCE_ID, createScope, parseComponentName, type Assets, @@ -16,7 +17,7 @@ import { type Styles, } from "@webstudio-is/sdk"; import type { WsComponentMeta } from "../components/component-meta"; -import { descendantComponent } from "../core-components"; +import { descendantComponent, rootComponent } from "../core-components"; import { addGlobalRules } from "./global-rules"; import { kebabCase } from "change-case"; @@ -90,7 +91,10 @@ export const generateCss = ({ // use :where() to reset specificity of preset selector // and let user styles completely override it // ideally switch to @layer when better supported - const rule = globalSheet.addNestingRule(`:where(${tag}.${className})`); + // render root preset styles without changes + const selector = + component === rootComponent ? ":root" : `:where(${tag}.${className})`; + const rule = globalSheet.addNestingRule(selector); for (const declaration of styles) { rule.setDeclaration({ breakpoint: "presets", @@ -146,6 +150,13 @@ export const generateCss = ({ for (const selection of styleSourceSelections.values()) { let { instanceId } = selection; const { values } = selection; + // special case for :root styles + if (instanceId === ROOT_INSTANCE_ID) { + const rule = sheet.addNestingRule(`:root`); + rule.applyMixins(values); + // avoid storing in instanceByRule to prevent conversion into atomic styles + continue; + } let descendantSuffix = ""; // render selector component as descendant selector const instance = instances.get(instanceId); @@ -176,7 +187,7 @@ export const generateCss = ({ if (atomic) { const { cssText } = generateAtomic(sheet, { - getKey: (rule) => instanceByRule.get(rule) ?? "", + getKey: (rule) => instanceByRule.get(rule), transformValue: imageValueTransformer, classes, }); diff --git a/packages/react-sdk/src/css/global-rules.ts b/packages/react-sdk/src/css/global-rules.ts index 1652af2eb536..bfed9ce15a07 100644 --- a/packages/react-sdk/src/css/global-rules.ts +++ b/packages/react-sdk/src/css/global-rules.ts @@ -6,12 +6,6 @@ export const addGlobalRules = ( sheet: StyleSheetRegular, { assets, assetBaseUrl }: { assets: Assets; assetBaseUrl: string } ) => { - // @todo we need to figure out all global resets while keeping - // the engine aware of all of them. - // Ideally, the user is somehow aware and in control of the reset - // Layout source https://twitter.com/ChallengesCss/status/1471128244720181258 - sheet.addPlaintextRule("html {margin: 0; display: grid; min-height: 100%}"); - const fontAssets: FontAsset[] = []; for (const asset of assets.values()) { if (asset.type === "font") { diff --git a/packages/sdk/src/__generated__/normalize.css.ts b/packages/sdk/src/__generated__/normalize.css.ts index b6e278167a3f..f8ca23f2ef9c 100644 --- a/packages/sdk/src/__generated__/normalize.css.ts +++ b/packages/sdk/src/__generated__/normalize.css.ts @@ -77,28 +77,16 @@ export const p = div; export const span = div; export const html: StyleDecl[] = [ + { property: "display", value: { type: "keyword", value: "grid" } }, + { property: "minHeight", value: { type: "unit", unit: "%", value: 100 } }, { - property: "lineHeight", - value: { type: "unit", unit: "number", value: 1.15 }, - }, - { - property: "textSizeAdjust", - value: { type: "unit", unit: "%", value: 100 }, - }, - { property: "tabSize", value: { type: "unit", unit: "number", value: 4 } }, - { property: "boxSizing", value: { type: "keyword", value: "border-box" } }, - { property: "borderTopWidth", value: { type: "unit", unit: "px", value: 1 } }, - { - property: "borderRightWidth", - value: { type: "unit", unit: "px", value: 1 }, - }, - { - property: "borderBottomWidth", - value: { type: "unit", unit: "px", value: 1 }, + property: "fontFamily", + value: { type: "fontFamily", value: ["Arial", "Roboto", "sans-serif"] }, }, + { property: "fontSize", value: { type: "unit", unit: "px", value: 16 } }, { - property: "borderLeftWidth", - value: { type: "unit", unit: "px", value: 1 }, + property: "lineHeight", + value: { type: "unit", unit: "number", value: 1.2 }, }, ]; @@ -113,15 +101,6 @@ export const body: StyleDecl[] = [ value: { type: "unit", unit: "number", value: 0 }, }, { property: "marginLeft", value: { type: "unit", unit: "number", value: 0 } }, - { - property: "fontFamily", - value: { type: "fontFamily", value: ["Arial", "Roboto", "sans-serif"] }, - }, - { property: "fontSize", value: { type: "unit", unit: "px", value: 16 } }, - { - property: "lineHeight", - value: { type: "unit", unit: "number", value: 1.2 }, - }, { property: "boxSizing", value: { type: "keyword", value: "border-box" } }, { property: "borderTopWidth", value: { type: "unit", unit: "px", value: 1 } }, { diff --git a/packages/sdk/src/instances-utils.ts b/packages/sdk/src/instances-utils.ts index 3f1983791d09..568fab04ca19 100644 --- a/packages/sdk/src/instances-utils.ts +++ b/packages/sdk/src/instances-utils.ts @@ -1,5 +1,7 @@ import type { Instance, Instances } from "./schema/instances"; +export const ROOT_INSTANCE_ID = ":root"; + const traverseInstances = ( instances: Instances, instanceId: Instance["id"], diff --git a/packages/sdk/src/normalize.css b/packages/sdk/src/normalize.css index 23afbd35cfde..fa2397464aa7 100644 --- a/packages/sdk/src/normalize.css +++ b/packages/sdk/src/normalize.css @@ -60,35 +60,26 @@ span { outline-width: 1px; } -/* @todo for now not applied to html, as we don't have html element */ /** - * 1. Correct the line height in all browsers. - * 2. Prevent adjustments of font size after orientation changes in iOS. - * 3. Use a more readable tab size (opinionated). + * 1. Layout source https://twitter.com/ChallengesCss/status/1471128244720181258 + * 2. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) */ html { /* 1 */ - line-height: 1.15; + display: grid; + min-height: 100%; /* 2 */ - -webkit-text-size-adjust: 100%; - /* 3 */ - tab-size: 4; - /* webstudio custom opinionated presets */ - box-sizing: border-box; - border-width: 1px; + font-family: Arial, Roboto, sans-serif; + font-size: 16px; + line-height: 1.2; } /** * 1. Remove the margin in all browsers. - * 2. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) */ body { /* 1 */ margin: 0; - /* 2 */ - font-family: Arial, Roboto, sans-serif; - font-size: 16px; - line-height: 1.2; /* webstudio custom opinionated presets */ box-sizing: border-box; border-width: 1px; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7d6e4a5da5c4..e53f92b2867b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -410,8 +410,8 @@ importers: specifier: ^1.3.3 version: 1.3.3 title-case: - specifier: ^4.3.1 - version: 4.3.1 + specifier: ^4.3.2 + version: 4.3.2 ultraflag: specifier: ^0.1.0 version: 0.1.0 @@ -1233,8 +1233,8 @@ importers: packages/css-engine: dependencies: '@emotion/hash': - specifier: ^0.9.1 - version: 0.9.1 + specifier: ^0.9.2 + version: 0.9.2 '@webstudio-is/error-utils': specifier: workspace:* version: link:../error-utils @@ -1833,8 +1833,8 @@ importers: specifier: ^5.0.1 version: 5.0.1 title-case: - specifier: ^4.3.1 - version: 4.3.1 + specifier: ^4.3.2 + version: 4.3.2 devDependencies: '@jest/globals': specifier: ^29.7.0 @@ -2652,8 +2652,8 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - '@emotion/hash@0.9.1': - resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} + '@emotion/hash@0.9.2': + resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} '@esbuild-plugins/node-globals-polyfill@0.2.3': resolution: {integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==} @@ -8809,8 +8809,8 @@ packages: tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} - title-case@4.3.1: - resolution: {integrity: sha512-VnPxQ+/j0X2FZ4ceGq1oLruTLjtN5Ul4sam5ypd4mDZLm1eHwkwip1gLxqhON/j4qyTlUlfPKslE/t4NPSlxhg==} + title-case@4.3.2: + resolution: {integrity: sha512-I/nkcBo73mO42Idfv08jhInV61IMb61OdIFxk+B4Gu1oBjWBPOLmhZdsli+oJCVaD+86pYQA93cJfFt224ZFAA==} tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} @@ -10022,7 +10022,7 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@emotion/hash@0.9.1': {} + '@emotion/hash@0.9.2': {} '@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19)': dependencies: @@ -12566,7 +12566,7 @@ snapshots: '@vanilla-extract/css@1.15.3': dependencies: - '@emotion/hash': 0.9.1 + '@emotion/hash': 0.9.2 '@vanilla-extract/private': 1.0.5 css-what: 6.1.0 cssesc: 3.0.0 @@ -17155,7 +17155,7 @@ snapshots: tiny-invariant@1.3.3: {} - title-case@4.3.1: {} + title-case@4.3.2: {} tmpl@1.0.5: {}