@webstudio-is/react-sdk 0.95.0 → 0.96.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/css/normalize.js +127 -53
- package/lib/index.js +1843 -32
- package/lib/types/index.d.ts +0 -1
- package/package.json +6 -7
- package/lib/app/index.js +0 -2
- package/lib/app/root.js +0 -18
- package/lib/component-renderer.js +0 -130
- package/lib/components/component-meta.js +0 -62
- package/lib/components/components-utils.js +0 -2
- package/lib/context.js +0 -21
- package/lib/css/css.js +0 -59
- package/lib/css/global-rules.js +0 -15
- package/lib/css/index.js +0 -4
- package/lib/css/normalize-type-check.js +0 -4
- package/lib/css/presets.js +0 -25
- package/lib/css/style-rules.js +0 -63
- package/lib/css/style-rules.test.js +0 -149
- package/lib/embed-template.js +0 -341
- package/lib/embed-template.test.js +0 -648
- package/lib/expression.js +0 -330
- package/lib/expression.test.js +0 -281
- package/lib/generator.js +0 -112
- package/lib/generator.test.js +0 -166
- package/lib/hook.js +0 -12
- package/lib/hook.test.js +0 -15
- package/lib/instance-utils.js +0 -43
- package/lib/instance-utils.test.js +0 -65
- package/lib/prop-meta.js +0 -150
- package/lib/props.js +0 -176
- package/lib/props.test.js +0 -159
- package/lib/pubsub/create.js +0 -56
- package/lib/pubsub/index.js +0 -2
- package/lib/pubsub/raf-queue.js +0 -20
- package/lib/tree/create-elements-tree.js +0 -134
- package/lib/tree/index.js +0 -4
- package/lib/tree/root.js +0 -85
- package/lib/tree/webstudio-component.js +0 -61
- package/lib/types/pubsub/create.d.ts +0 -28
- package/lib/types/pubsub/index.d.ts +0 -1
- package/lib/types/pubsub/raf-queue.d.ts +0 -1
package/lib/types/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webstudio-is/react-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.96.0",
|
|
4
4
|
"description": "Webstudio JavaScript / TypeScript API",
|
|
5
5
|
"author": "Webstudio <github@webstudio.is>",
|
|
6
6
|
"homepage": "https://webstudio.is",
|
|
@@ -30,14 +30,13 @@
|
|
|
30
30
|
"@nanostores/react": "^0.7.1",
|
|
31
31
|
"html-tags": "^3.3.1",
|
|
32
32
|
"jsep": "^1.3.8",
|
|
33
|
-
"nanoevents": "^8.0.0",
|
|
34
33
|
"nanoid": "^4.0.2",
|
|
35
34
|
"nanostores": "^0.9.3",
|
|
36
35
|
"no-case": "^3.0.4",
|
|
37
36
|
"title-case": "^3.0.3",
|
|
38
|
-
"@webstudio-is/css-engine": "^0.
|
|
39
|
-
"@webstudio-is/fonts": "^0.
|
|
40
|
-
"@webstudio-is/sdk": "^0.
|
|
37
|
+
"@webstudio-is/css-engine": "^0.96.0",
|
|
38
|
+
"@webstudio-is/fonts": "^0.96.0",
|
|
39
|
+
"@webstudio-is/sdk": "^0.96.0"
|
|
41
40
|
},
|
|
42
41
|
"exports": {
|
|
43
42
|
".": {
|
|
@@ -61,8 +60,8 @@
|
|
|
61
60
|
"private": false,
|
|
62
61
|
"sideEffects": false,
|
|
63
62
|
"scripts": {
|
|
64
|
-
"dev": "
|
|
65
|
-
"build": "rm -rf lib && esbuild
|
|
63
|
+
"dev": "rm -rf lib && esbuild 'src/**/*.ts' 'src/**/*.tsx' --outdir=lib --watch",
|
|
64
|
+
"build": "rm -rf lib && esbuild src/index.ts ./src/css/normalize.ts --outdir=lib --bundle --format=esm --packages=external",
|
|
66
65
|
"dts": "tsc --project tsconfig.dts.json",
|
|
67
66
|
"typecheck": "tsc",
|
|
68
67
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests",
|
package/lib/app/index.js
DELETED
package/lib/app/root.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Links, Meta, Outlet as DefaultOutlet } from "@remix-run/react";
|
|
4
|
-
export const Root = ({
|
|
5
|
-
Outlet = DefaultOutlet
|
|
6
|
-
}) => {
|
|
7
|
-
return /* @__PURE__ */ jsxs("html", { lang: "en", children: [
|
|
8
|
-
/* @__PURE__ */ jsxs("head", { children: [
|
|
9
|
-
/* @__PURE__ */ jsx("meta", { charSet: "utf-8" }),
|
|
10
|
-
/* @__PURE__ */ jsx("meta", { name: "viewport", content: "width=device-width,initial-scale=1" }),
|
|
11
|
-
/* @__PURE__ */ jsx("link", { rel: "icon", href: "/favicon.ico", type: "image/x-icon" }),
|
|
12
|
-
/* @__PURE__ */ jsx("link", { rel: "shortcut icon", href: "/favicon.ico", type: "image/x-icon" }),
|
|
13
|
-
/* @__PURE__ */ jsx(Meta, {}),
|
|
14
|
-
/* @__PURE__ */ jsx(Links, {})
|
|
15
|
-
] }),
|
|
16
|
-
/* @__PURE__ */ jsx(Outlet, {})
|
|
17
|
-
] });
|
|
18
|
-
};
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { getStyleDeclKey } from "@webstudio-is/sdk";
|
|
4
|
-
import {
|
|
5
|
-
WsEmbedTemplate,
|
|
6
|
-
generateDataFromEmbedTemplate
|
|
7
|
-
} from "./embed-template";
|
|
8
|
-
import { generateCssText } from "./css";
|
|
9
|
-
import { InstanceRoot, WebstudioComponent } from "./tree";
|
|
10
|
-
import {
|
|
11
|
-
decodeVariablesMap,
|
|
12
|
-
encodeDataSourceVariable,
|
|
13
|
-
encodeVariablesMap,
|
|
14
|
-
executeComputingExpressions,
|
|
15
|
-
executeEffectfulExpression
|
|
16
|
-
} from "./expression";
|
|
17
|
-
import { getIndexesWithinAncestors } from "./instance-utils";
|
|
18
|
-
export const renderComponentTemplate = ({
|
|
19
|
-
name,
|
|
20
|
-
metas: metasRecord,
|
|
21
|
-
components,
|
|
22
|
-
props
|
|
23
|
-
}) => {
|
|
24
|
-
const metas = new Map(Object.entries(metasRecord));
|
|
25
|
-
const template = metas.get(name)?.template ?? [
|
|
26
|
-
{
|
|
27
|
-
type: "instance",
|
|
28
|
-
component: name,
|
|
29
|
-
children: []
|
|
30
|
-
}
|
|
31
|
-
];
|
|
32
|
-
if (template[0].type === "instance" && props !== void 0) {
|
|
33
|
-
template[0].props = Object.entries(props).map(([prop, value]) => {
|
|
34
|
-
if (typeof value === "string") {
|
|
35
|
-
return { type: "string", name: prop, value };
|
|
36
|
-
}
|
|
37
|
-
if (typeof value === "number") {
|
|
38
|
-
return { type: "number", name: prop, value };
|
|
39
|
-
}
|
|
40
|
-
if (typeof value === "boolean") {
|
|
41
|
-
return { type: "boolean", name: prop, value };
|
|
42
|
-
}
|
|
43
|
-
throw new Error(`Unsupported prop ${props} with value ${value}`);
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
const data = generateDataFromEmbedTemplate(template, metas, "base");
|
|
47
|
-
const instances = [
|
|
48
|
-
[
|
|
49
|
-
"root",
|
|
50
|
-
{
|
|
51
|
-
type: "instance",
|
|
52
|
-
id: "root",
|
|
53
|
-
component: "Box",
|
|
54
|
-
children: data.children
|
|
55
|
-
}
|
|
56
|
-
],
|
|
57
|
-
...data.instances.map(
|
|
58
|
-
(instance) => [instance.id, instance]
|
|
59
|
-
)
|
|
60
|
-
];
|
|
61
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
62
|
-
/* @__PURE__ */ jsx("style", { children: generateCssText(
|
|
63
|
-
{
|
|
64
|
-
assets: [],
|
|
65
|
-
breakpoints: [["base", { id: "base", label: "base" }]],
|
|
66
|
-
styles: data.styles.map((item) => [getStyleDeclKey(item), item]),
|
|
67
|
-
styleSourceSelections: data.styleSourceSelections.map((item) => [
|
|
68
|
-
item.instanceId,
|
|
69
|
-
item
|
|
70
|
-
]),
|
|
71
|
-
componentMetas: metas
|
|
72
|
-
},
|
|
73
|
-
{ assetBaseUrl: "/" }
|
|
74
|
-
) }),
|
|
75
|
-
/* @__PURE__ */ jsx(
|
|
76
|
-
InstanceRoot,
|
|
77
|
-
{
|
|
78
|
-
data: {
|
|
79
|
-
page: {
|
|
80
|
-
path: "",
|
|
81
|
-
id: "",
|
|
82
|
-
name: "",
|
|
83
|
-
title: "",
|
|
84
|
-
meta: {},
|
|
85
|
-
rootInstanceId: "root"
|
|
86
|
-
},
|
|
87
|
-
pages: [],
|
|
88
|
-
assets: [],
|
|
89
|
-
build: {
|
|
90
|
-
instances,
|
|
91
|
-
props: data.props.map((prop) => [prop.id, prop]),
|
|
92
|
-
dataSources: data.dataSources.map((dataSource) => [
|
|
93
|
-
dataSource.id,
|
|
94
|
-
dataSource
|
|
95
|
-
])
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
utils: {
|
|
99
|
-
indexesWithinAncestors: getIndexesWithinAncestors(
|
|
100
|
-
metas,
|
|
101
|
-
new Map(instances),
|
|
102
|
-
["root"]
|
|
103
|
-
),
|
|
104
|
-
executeComputingExpressions: (values) => {
|
|
105
|
-
const expressions = /* @__PURE__ */ new Map();
|
|
106
|
-
for (const dataSource of data.dataSources) {
|
|
107
|
-
const name2 = encodeDataSourceVariable(dataSource.id);
|
|
108
|
-
if (dataSource.type === "expression") {
|
|
109
|
-
expressions.set(name2, dataSource.code);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return decodeVariablesMap(
|
|
113
|
-
executeComputingExpressions(
|
|
114
|
-
expressions,
|
|
115
|
-
encodeVariablesMap(values)
|
|
116
|
-
)
|
|
117
|
-
);
|
|
118
|
-
},
|
|
119
|
-
executeEffectfulExpression: (code, args, values) => {
|
|
120
|
-
return decodeVariablesMap(
|
|
121
|
-
executeEffectfulExpression(code, args, encodeVariablesMap(values))
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
Component: WebstudioComponent,
|
|
126
|
-
components: new Map(Object.entries(components))
|
|
127
|
-
}
|
|
128
|
-
)
|
|
129
|
-
] });
|
|
130
|
-
};
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import { PropMeta } from "../prop-meta";
|
|
4
|
-
import { EmbedTemplateStyleDecl, WsEmbedTemplate } from "../embed-template";
|
|
5
|
-
const WsComponentPropsMeta = z.object({
|
|
6
|
-
props: z.record(PropMeta),
|
|
7
|
-
// Props that will be always visible in properties panel.
|
|
8
|
-
initialProps: z.array(z.string()).optional()
|
|
9
|
-
});
|
|
10
|
-
export const componentCategories = [
|
|
11
|
-
"general",
|
|
12
|
-
"text",
|
|
13
|
-
"media",
|
|
14
|
-
"forms",
|
|
15
|
-
"radix",
|
|
16
|
-
"hidden"
|
|
17
|
-
];
|
|
18
|
-
export const stateCategories = ["states", "component-states"];
|
|
19
|
-
export const ComponentState = z.object({
|
|
20
|
-
category: z.enum(stateCategories).optional(),
|
|
21
|
-
selector: z.string(),
|
|
22
|
-
label: z.string()
|
|
23
|
-
});
|
|
24
|
-
const ComponentToken = z.object({
|
|
25
|
-
variant: z.optional(z.string()),
|
|
26
|
-
styles: z.array(EmbedTemplateStyleDecl)
|
|
27
|
-
});
|
|
28
|
-
export const defaultStates = [
|
|
29
|
-
{ selector: ":hover", label: "Hover" },
|
|
30
|
-
{ selector: ":active", label: "Active" },
|
|
31
|
-
{ selector: ":focus", label: "Focus" },
|
|
32
|
-
{ selector: ":focus-visible", label: "Focus Visible" },
|
|
33
|
-
{ selector: ":focus-within", label: "Focus Within" }
|
|
34
|
-
];
|
|
35
|
-
const WsComponentMeta = z.object({
|
|
36
|
-
category: z.enum(componentCategories).optional(),
|
|
37
|
-
// container - can accept other components with dnd or be edited as text
|
|
38
|
-
// control - usually form controls like inputs, without children
|
|
39
|
-
// embed - images, videos or other embeddable components, without children
|
|
40
|
-
// rich-text-child - formatted text fragment, not listed in components list
|
|
41
|
-
type: z.enum(["container", "control", "embed", "rich-text-child"]),
|
|
42
|
-
requiredAncestors: z.optional(z.array(z.string())),
|
|
43
|
-
invalidAncestors: z.optional(z.array(z.string())),
|
|
44
|
-
// when this field is specified component receives
|
|
45
|
-
// prop with index of same components withiin specified ancestor
|
|
46
|
-
// important to automatically enumerate collections without
|
|
47
|
-
// naming every item manually
|
|
48
|
-
indexWithinAncestor: z.optional(z.string()),
|
|
49
|
-
stylable: z.optional(z.boolean()),
|
|
50
|
-
// specifies whether the instance can be deleted,
|
|
51
|
-
// copied or dragged out of its parent instance
|
|
52
|
-
// true by default
|
|
53
|
-
detachable: z.optional(z.boolean()),
|
|
54
|
-
label: z.optional(z.string()),
|
|
55
|
-
description: z.string().optional(),
|
|
56
|
-
icon: z.string(),
|
|
57
|
-
presetStyle: z.optional(z.record(z.string(), EmbedTemplateStyleDecl)),
|
|
58
|
-
presetTokens: z.optional(z.record(z.string(), ComponentToken)),
|
|
59
|
-
states: z.optional(z.array(ComponentState)),
|
|
60
|
-
template: z.optional(WsEmbedTemplate),
|
|
61
|
-
order: z.number().optional()
|
|
62
|
-
});
|
package/lib/context.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { atom } from "nanostores";
|
|
3
|
-
import { createContext } from "react";
|
|
4
|
-
export const ReactSdkContext = createContext({
|
|
5
|
-
imageBaseUrl: "/",
|
|
6
|
-
assetBaseUrl: "/",
|
|
7
|
-
propsByInstanceIdStore: atom(/* @__PURE__ */ new Map()),
|
|
8
|
-
assetsStore: atom(/* @__PURE__ */ new Map()),
|
|
9
|
-
pagesStore: atom(/* @__PURE__ */ new Map()),
|
|
10
|
-
dataSourceValuesStore: atom(/* @__PURE__ */ new Map()),
|
|
11
|
-
executeEffectfulExpression: () => {
|
|
12
|
-
throw Error("React SDK executeEffectfulExpression is not implemented");
|
|
13
|
-
},
|
|
14
|
-
setDataSourceValues: () => {
|
|
15
|
-
throw Error("React SDK setBoundDataSourceValue is not implemented");
|
|
16
|
-
},
|
|
17
|
-
setBoundDataSourceValue: () => {
|
|
18
|
-
throw Error("React SDK setBoundDataSourceValue is not implemented");
|
|
19
|
-
},
|
|
20
|
-
indexesWithinAncestors: /* @__PURE__ */ new Map()
|
|
21
|
-
});
|
package/lib/css/css.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { createCssEngine } from "@webstudio-is/css-engine";
|
|
3
|
-
import { idAttribute } from "../tree";
|
|
4
|
-
import { addGlobalRules } from "./global-rules";
|
|
5
|
-
import { getPresetStyleRules, getStyleRules } from "./style-rules";
|
|
6
|
-
export const createImageValueTransformer = (assets, options) => (styleValue) => {
|
|
7
|
-
if (styleValue.type === "image" && styleValue.value.type === "asset") {
|
|
8
|
-
const asset = assets.get(styleValue.value.value);
|
|
9
|
-
if (asset === void 0) {
|
|
10
|
-
return { type: "keyword", value: "none" };
|
|
11
|
-
}
|
|
12
|
-
const { assetBaseUrl } = options;
|
|
13
|
-
const url = `${assetBaseUrl}${asset.name}`;
|
|
14
|
-
return {
|
|
15
|
-
type: "image",
|
|
16
|
-
value: {
|
|
17
|
-
type: "url",
|
|
18
|
-
url
|
|
19
|
-
},
|
|
20
|
-
hidden: styleValue.hidden
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
export const generateCssText = (data, options) => {
|
|
25
|
-
const assets = new Map(data.assets.map((asset) => [asset.id, asset]));
|
|
26
|
-
const breakpoints = new Map(data.breakpoints);
|
|
27
|
-
const styles = new Map(data.styles);
|
|
28
|
-
const styleSourceSelections = new Map(data.styleSourceSelections);
|
|
29
|
-
const engine = createCssEngine({ name: "ssr" });
|
|
30
|
-
addGlobalRules(engine, {
|
|
31
|
-
assets,
|
|
32
|
-
assetBaseUrl: options.assetBaseUrl
|
|
33
|
-
});
|
|
34
|
-
for (const breakpoint of breakpoints.values()) {
|
|
35
|
-
engine.addMediaRule(breakpoint.id, breakpoint);
|
|
36
|
-
}
|
|
37
|
-
for (const [component, meta] of data.componentMetas) {
|
|
38
|
-
const presetStyle = meta.presetStyle;
|
|
39
|
-
if (presetStyle === void 0) {
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
const rules = getPresetStyleRules(component, presetStyle);
|
|
43
|
-
for (const [selector, style] of rules) {
|
|
44
|
-
engine.addStyleRule(selector, { style });
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
const styleRules = getStyleRules(styles, styleSourceSelections);
|
|
48
|
-
for (const { breakpointId, instanceId, state, style } of styleRules) {
|
|
49
|
-
engine.addStyleRule(
|
|
50
|
-
`[${idAttribute}="${instanceId}"]${state ?? ""}`,
|
|
51
|
-
{
|
|
52
|
-
breakpoint: breakpointId,
|
|
53
|
-
style
|
|
54
|
-
},
|
|
55
|
-
createImageValueTransformer(assets, options)
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
return engine.cssText;
|
|
59
|
-
};
|
package/lib/css/global-rules.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { getFontFaces } from "@webstudio-is/fonts";
|
|
3
|
-
export const addGlobalRules = (engine, { assets, assetBaseUrl }) => {
|
|
4
|
-
engine.addPlaintextRule("html {margin: 0; display: grid; min-height: 100%}");
|
|
5
|
-
const fontAssets = [];
|
|
6
|
-
for (const asset of assets.values()) {
|
|
7
|
-
if (asset.type === "font") {
|
|
8
|
-
fontAssets.push(asset);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
const fontFaces = getFontFaces(fontAssets, { assetBaseUrl });
|
|
12
|
-
for (const fontFace of fontFaces) {
|
|
13
|
-
engine.addFontFaceRule(fontFace);
|
|
14
|
-
}
|
|
15
|
-
};
|
package/lib/css/index.js
DELETED
package/lib/css/presets.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
export const borders = [
|
|
3
|
-
{
|
|
4
|
-
property: "borderTopWidth",
|
|
5
|
-
value: { type: "unit", value: 1, unit: "px" }
|
|
6
|
-
},
|
|
7
|
-
{
|
|
8
|
-
property: "borderRightWidth",
|
|
9
|
-
value: { type: "unit", value: 1, unit: "px" }
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
property: "borderBottomWidth",
|
|
13
|
-
value: { type: "unit", value: 1, unit: "px" }
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
property: "borderLeftWidth",
|
|
17
|
-
value: { type: "unit", value: 1, unit: "px" }
|
|
18
|
-
}
|
|
19
|
-
];
|
|
20
|
-
export const outline = [
|
|
21
|
-
{
|
|
22
|
-
property: "outlineWidth",
|
|
23
|
-
value: { type: "unit", value: 1, unit: "px" }
|
|
24
|
-
}
|
|
25
|
-
];
|
package/lib/css/style-rules.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { componentAttribute } from "../tree";
|
|
3
|
-
export const getStyleRules = (styles, styleSourceSelections) => {
|
|
4
|
-
if (styles === void 0 || styleSourceSelections === void 0) {
|
|
5
|
-
return [];
|
|
6
|
-
}
|
|
7
|
-
const stylesByStyleSourceId = /* @__PURE__ */ new Map();
|
|
8
|
-
for (const styleDecl of styles.values()) {
|
|
9
|
-
const { styleSourceId } = styleDecl;
|
|
10
|
-
let styleSourceStyles = stylesByStyleSourceId.get(styleSourceId);
|
|
11
|
-
if (styleSourceStyles === void 0) {
|
|
12
|
-
styleSourceStyles = [];
|
|
13
|
-
stylesByStyleSourceId.set(styleSourceId, styleSourceStyles);
|
|
14
|
-
}
|
|
15
|
-
styleSourceStyles.push(styleDecl);
|
|
16
|
-
}
|
|
17
|
-
const styleRules = [];
|
|
18
|
-
for (const { instanceId, values } of styleSourceSelections.values()) {
|
|
19
|
-
const styleRuleByBreakpointId = /* @__PURE__ */ new Map();
|
|
20
|
-
for (const styleSourceId of values) {
|
|
21
|
-
const styleSourceStyles = stylesByStyleSourceId.get(styleSourceId);
|
|
22
|
-
if (styleSourceStyles === void 0) {
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
for (const {
|
|
26
|
-
breakpointId,
|
|
27
|
-
state,
|
|
28
|
-
property,
|
|
29
|
-
value
|
|
30
|
-
} of styleSourceStyles) {
|
|
31
|
-
const key = `${breakpointId}:${state ?? ""}`;
|
|
32
|
-
let styleRule = styleRuleByBreakpointId.get(key);
|
|
33
|
-
if (styleRule === void 0) {
|
|
34
|
-
styleRule = {
|
|
35
|
-
instanceId,
|
|
36
|
-
breakpointId,
|
|
37
|
-
state,
|
|
38
|
-
style: {}
|
|
39
|
-
};
|
|
40
|
-
styleRuleByBreakpointId.set(key, styleRule);
|
|
41
|
-
}
|
|
42
|
-
styleRule.style[property] = value;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
styleRules.push(...styleRuleByBreakpointId.values());
|
|
46
|
-
}
|
|
47
|
-
return styleRules;
|
|
48
|
-
};
|
|
49
|
-
export const getPresetStyleRules = (component, presetStyle) => {
|
|
50
|
-
const presetStyleRules = /* @__PURE__ */ new Map();
|
|
51
|
-
for (const [tag, styles] of Object.entries(presetStyle)) {
|
|
52
|
-
for (const styleDecl of styles) {
|
|
53
|
-
const selector = `${tag}:where([${componentAttribute}="${component}"])${styleDecl.state ?? ""}`;
|
|
54
|
-
let rule = presetStyleRules.get(selector);
|
|
55
|
-
if (rule === void 0) {
|
|
56
|
-
rule = {};
|
|
57
|
-
presetStyleRules.set(selector, rule);
|
|
58
|
-
}
|
|
59
|
-
rule[styleDecl.property] = styleDecl.value;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return presetStyleRules;
|
|
63
|
-
};
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { test, expect } from "@jest/globals";
|
|
3
|
-
import {
|
|
4
|
-
getStyleDeclKey
|
|
5
|
-
} from "@webstudio-is/sdk";
|
|
6
|
-
import { getStyleRules } from "./style-rules";
|
|
7
|
-
const createStyleDeclPair = (styleDecl) => {
|
|
8
|
-
return [getStyleDeclKey(styleDecl), styleDecl];
|
|
9
|
-
};
|
|
10
|
-
test("compute styles from different style sources", () => {
|
|
11
|
-
const styles = new Map([
|
|
12
|
-
createStyleDeclPair({
|
|
13
|
-
breakpointId: "a",
|
|
14
|
-
styleSourceId: "styleSource1",
|
|
15
|
-
property: "width",
|
|
16
|
-
value: { type: "unit", value: 10, unit: "px" }
|
|
17
|
-
}),
|
|
18
|
-
createStyleDeclPair({
|
|
19
|
-
breakpointId: "a",
|
|
20
|
-
styleSourceId: "styleSource2",
|
|
21
|
-
property: "display",
|
|
22
|
-
value: { type: "keyword", value: "block" }
|
|
23
|
-
}),
|
|
24
|
-
createStyleDeclPair({
|
|
25
|
-
breakpointId: "a",
|
|
26
|
-
styleSourceId: "styleSource4",
|
|
27
|
-
property: "color",
|
|
28
|
-
value: { type: "keyword", value: "green" }
|
|
29
|
-
}),
|
|
30
|
-
createStyleDeclPair({
|
|
31
|
-
breakpointId: "a",
|
|
32
|
-
styleSourceId: "styleSource4",
|
|
33
|
-
property: "width",
|
|
34
|
-
value: { type: "keyword", value: "min-content" }
|
|
35
|
-
}),
|
|
36
|
-
createStyleDeclPair({
|
|
37
|
-
breakpointId: "a",
|
|
38
|
-
styleSourceId: "styleSource3",
|
|
39
|
-
property: "color",
|
|
40
|
-
value: { type: "keyword", value: "red" }
|
|
41
|
-
}),
|
|
42
|
-
createStyleDeclPair({
|
|
43
|
-
breakpointId: "b",
|
|
44
|
-
styleSourceId: "styleSource5",
|
|
45
|
-
property: "color",
|
|
46
|
-
value: { type: "keyword", value: "orange" }
|
|
47
|
-
}),
|
|
48
|
-
createStyleDeclPair({
|
|
49
|
-
breakpointId: "a",
|
|
50
|
-
styleSourceId: "styleSource6",
|
|
51
|
-
property: "color",
|
|
52
|
-
value: { type: "keyword", value: "blue" }
|
|
53
|
-
}),
|
|
54
|
-
createStyleDeclPair({
|
|
55
|
-
breakpointId: "a",
|
|
56
|
-
styleSourceId: "styleSource6",
|
|
57
|
-
state: ":hover",
|
|
58
|
-
property: "color",
|
|
59
|
-
value: { type: "keyword", value: "blue" }
|
|
60
|
-
})
|
|
61
|
-
]);
|
|
62
|
-
const styleSourceSelections = /* @__PURE__ */ new Map([
|
|
63
|
-
[
|
|
64
|
-
"instance1",
|
|
65
|
-
{
|
|
66
|
-
instanceId: "instance1",
|
|
67
|
-
values: ["styleSource1"]
|
|
68
|
-
}
|
|
69
|
-
],
|
|
70
|
-
[
|
|
71
|
-
"instance2",
|
|
72
|
-
{
|
|
73
|
-
instanceId: "instance2",
|
|
74
|
-
values: ["styleSource4", "styleSource5", "styleSource3"]
|
|
75
|
-
}
|
|
76
|
-
],
|
|
77
|
-
[
|
|
78
|
-
"instance3",
|
|
79
|
-
{
|
|
80
|
-
instanceId: "instance3",
|
|
81
|
-
values: ["styleSource6"]
|
|
82
|
-
}
|
|
83
|
-
]
|
|
84
|
-
]);
|
|
85
|
-
expect(getStyleRules(styles, styleSourceSelections)).toMatchInlineSnapshot(`
|
|
86
|
-
[
|
|
87
|
-
{
|
|
88
|
-
"breakpointId": "a",
|
|
89
|
-
"instanceId": "instance1",
|
|
90
|
-
"state": undefined,
|
|
91
|
-
"style": {
|
|
92
|
-
"width": {
|
|
93
|
-
"type": "unit",
|
|
94
|
-
"unit": "px",
|
|
95
|
-
"value": 10,
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
"breakpointId": "a",
|
|
101
|
-
"instanceId": "instance2",
|
|
102
|
-
"state": undefined,
|
|
103
|
-
"style": {
|
|
104
|
-
"color": {
|
|
105
|
-
"type": "keyword",
|
|
106
|
-
"value": "red",
|
|
107
|
-
},
|
|
108
|
-
"width": {
|
|
109
|
-
"type": "keyword",
|
|
110
|
-
"value": "min-content",
|
|
111
|
-
},
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
"breakpointId": "b",
|
|
116
|
-
"instanceId": "instance2",
|
|
117
|
-
"state": undefined,
|
|
118
|
-
"style": {
|
|
119
|
-
"color": {
|
|
120
|
-
"type": "keyword",
|
|
121
|
-
"value": "orange",
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
"breakpointId": "a",
|
|
127
|
-
"instanceId": "instance3",
|
|
128
|
-
"state": undefined,
|
|
129
|
-
"style": {
|
|
130
|
-
"color": {
|
|
131
|
-
"type": "keyword",
|
|
132
|
-
"value": "blue",
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
"breakpointId": "a",
|
|
138
|
-
"instanceId": "instance3",
|
|
139
|
-
"state": ":hover",
|
|
140
|
-
"style": {
|
|
141
|
-
"color": {
|
|
142
|
-
"type": "keyword",
|
|
143
|
-
"value": "blue",
|
|
144
|
-
},
|
|
145
|
-
},
|
|
146
|
-
},
|
|
147
|
-
]
|
|
148
|
-
`);
|
|
149
|
-
});
|