@webstudio-is/react-sdk 0.74.0 → 0.76.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/cjs/components/component-meta.js +1 -0
- package/lib/cjs/context.js +5 -1
- package/lib/cjs/css/global-rules.js +1 -1
- package/lib/cjs/css/normalize.js +10 -13
- package/lib/cjs/embed-template.js +68 -3
- package/lib/cjs/expression.js +191 -0
- package/lib/cjs/index.js +7 -1
- package/lib/cjs/props.js +28 -10
- package/lib/cjs/tree/create-elements-tree.js +14 -1
- package/lib/cjs/tree/root.js +55 -0
- package/lib/cjs/tree/webstudio-component.js +9 -2
- package/lib/components/component-meta.js +1 -0
- package/lib/context.js +5 -1
- package/lib/css/global-rules.js +1 -1
- package/lib/css/normalize.js +10 -13
- package/lib/embed-template.js +68 -3
- package/lib/expression.js +161 -0
- package/lib/index.js +13 -1
- package/lib/props.js +28 -10
- package/lib/tree/create-elements-tree.js +14 -1
- package/lib/tree/root.js +63 -1
- package/lib/tree/webstudio-component.js +9 -2
- package/lib/types/components/component-meta.d.ts +115 -0
- package/lib/types/context.d.ts +3 -0
- package/lib/types/css/normalize.d.ts +1316 -0
- package/lib/types/embed-template.d.ts +512 -0
- package/lib/types/expression.d.ts +6 -0
- package/lib/types/expression.test.d.ts +1 -0
- package/lib/types/index.d.ts +2 -1
- package/lib/types/props.d.ts +8 -7
- package/lib/types/tree/create-elements-tree.d.ts +4 -2
- package/lib/types/tree/root.d.ts +3 -3
- package/lib/types/tree/webstudio-component.d.ts +1 -0
- package/package.json +15 -15
- package/src/components/component-meta.ts +1 -0
- package/src/context.tsx +11 -0
- package/src/css/global-rules.ts +2 -1
- package/src/css/normalize.ts +10 -13
- package/src/embed-template.test.ts +177 -1
- package/src/embed-template.ts +73 -2
- package/src/expression.test.ts +122 -0
- package/src/expression.ts +183 -0
- package/src/index.ts +7 -0
- package/src/props.ts +29 -10
- package/src/tree/create-elements-tree.tsx +20 -1
- package/src/tree/root.ts +81 -4
- package/src/tree/webstudio-component.tsx +7 -1
|
@@ -63,6 +63,7 @@ const WsComponentMeta = import_zod.z.object({
|
|
|
63
63
|
invalidAncestors: import_zod.z.optional(import_zod.z.array(import_zod.z.string())),
|
|
64
64
|
stylable: import_zod.z.optional(import_zod.z.boolean()),
|
|
65
65
|
label: import_zod.z.string(),
|
|
66
|
+
description: import_zod.z.string().optional(),
|
|
66
67
|
icon: import_zod.z.string(),
|
|
67
68
|
presetStyle: import_zod.z.optional(import_zod.z.record(import_zod.z.string(), import_embed_template.EmbedTemplateStyleDecl)),
|
|
68
69
|
states: import_zod.z.optional(import_zod.z.array(ComponentState)),
|
package/lib/cjs/context.js
CHANGED
|
@@ -28,5 +28,9 @@ const ReactSdkContext = (0, import_react.createContext)({
|
|
|
28
28
|
assetBaseUrl: "/",
|
|
29
29
|
propsByInstanceIdStore: (0, import_nanostores.atom)(/* @__PURE__ */ new Map()),
|
|
30
30
|
assetsStore: (0, import_nanostores.atom)(/* @__PURE__ */ new Map()),
|
|
31
|
-
pagesStore: (0, import_nanostores.atom)(/* @__PURE__ */ new Map())
|
|
31
|
+
pagesStore: (0, import_nanostores.atom)(/* @__PURE__ */ new Map()),
|
|
32
|
+
dataSourceValuesStore: (0, import_nanostores.atom)(/* @__PURE__ */ new Map()),
|
|
33
|
+
setDataSourceValue: () => {
|
|
34
|
+
throw Error("React SDK setDataSourceValue is not implemented");
|
|
35
|
+
}
|
|
32
36
|
});
|
|
@@ -23,7 +23,7 @@ __export(global_rules_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(global_rules_exports);
|
|
24
24
|
var import_fonts = require("@webstudio-is/fonts");
|
|
25
25
|
const addGlobalRules = (engine, { assets, assetBaseUrl }) => {
|
|
26
|
-
engine.addPlaintextRule("html {margin: 0; height: 100%}");
|
|
26
|
+
engine.addPlaintextRule("html {margin: 0; display: grid; min-height: 100%}");
|
|
27
27
|
const fontAssets = [];
|
|
28
28
|
for (const asset of assets.values()) {
|
|
29
29
|
if (asset?.type === "font") {
|
package/lib/cjs/css/normalize.js
CHANGED
|
@@ -93,18 +93,7 @@ const h5 = baseStyle;
|
|
|
93
93
|
const h6 = baseStyle;
|
|
94
94
|
const i = baseStyle;
|
|
95
95
|
const img = baseStyle;
|
|
96
|
-
const a =
|
|
97
|
-
...baseStyle,
|
|
98
|
-
{
|
|
99
|
-
property: "color",
|
|
100
|
-
value: { type: "rgb", r: 0, g: 0, b: 238, alpha: 1 }
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
state: ":visited",
|
|
104
|
-
property: "color",
|
|
105
|
-
value: { type: "rgb", r: 85, g: 26, b: 139, alpha: 1 }
|
|
106
|
-
}
|
|
107
|
-
];
|
|
96
|
+
const a = baseStyle;
|
|
108
97
|
const li = baseStyle;
|
|
109
98
|
const ul = baseStyle;
|
|
110
99
|
const ol = baseStyle;
|
|
@@ -152,9 +141,17 @@ const body = [
|
|
|
152
141
|
property: "fontFamily",
|
|
153
142
|
value: {
|
|
154
143
|
type: "keyword",
|
|
155
|
-
value:
|
|
144
|
+
value: "Arial, sans-serif"
|
|
156
145
|
}
|
|
157
146
|
},
|
|
147
|
+
{
|
|
148
|
+
property: "fontSize",
|
|
149
|
+
value: { type: "unit", unit: "px", value: 16 }
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
property: "lineHeight",
|
|
153
|
+
value: { type: "unit", unit: "number", value: 1.2 }
|
|
154
|
+
},
|
|
158
155
|
boxSizing,
|
|
159
156
|
...import_presets.borders
|
|
160
157
|
];
|
|
@@ -27,29 +27,45 @@ module.exports = __toCommonJS(embed_template_exports);
|
|
|
27
27
|
var import_zod = require("zod");
|
|
28
28
|
var import_nanoid = require("nanoid");
|
|
29
29
|
var import_css_data = require("@webstudio-is/css-data");
|
|
30
|
+
var import_expression = require("./expression");
|
|
30
31
|
const EmbedTemplateText = import_zod.z.object({
|
|
31
32
|
type: import_zod.z.literal("text"),
|
|
32
33
|
value: import_zod.z.string()
|
|
33
34
|
});
|
|
35
|
+
const DataSourceRef = import_zod.z.union([
|
|
36
|
+
import_zod.z.object({
|
|
37
|
+
type: import_zod.z.literal("variable"),
|
|
38
|
+
name: import_zod.z.string()
|
|
39
|
+
}),
|
|
40
|
+
import_zod.z.object({
|
|
41
|
+
type: import_zod.z.literal("expression"),
|
|
42
|
+
name: import_zod.z.string(),
|
|
43
|
+
code: import_zod.z.string()
|
|
44
|
+
})
|
|
45
|
+
]);
|
|
34
46
|
const EmbedTemplateProp = import_zod.z.union([
|
|
35
47
|
import_zod.z.object({
|
|
36
48
|
type: import_zod.z.literal("number"),
|
|
37
49
|
name: import_zod.z.string(),
|
|
50
|
+
dataSourceRef: import_zod.z.optional(DataSourceRef),
|
|
38
51
|
value: import_zod.z.number()
|
|
39
52
|
}),
|
|
40
53
|
import_zod.z.object({
|
|
41
54
|
type: import_zod.z.literal("string"),
|
|
42
55
|
name: import_zod.z.string(),
|
|
56
|
+
dataSourceRef: import_zod.z.optional(DataSourceRef),
|
|
43
57
|
value: import_zod.z.string()
|
|
44
58
|
}),
|
|
45
59
|
import_zod.z.object({
|
|
46
60
|
type: import_zod.z.literal("boolean"),
|
|
47
61
|
name: import_zod.z.string(),
|
|
62
|
+
dataSourceRef: import_zod.z.optional(DataSourceRef),
|
|
48
63
|
value: import_zod.z.boolean()
|
|
49
64
|
}),
|
|
50
65
|
import_zod.z.object({
|
|
51
66
|
type: import_zod.z.literal("string[]"),
|
|
52
67
|
name: import_zod.z.string(),
|
|
68
|
+
dataSourceRef: import_zod.z.optional(DataSourceRef),
|
|
53
69
|
value: import_zod.z.array(import_zod.z.string())
|
|
54
70
|
})
|
|
55
71
|
]);
|
|
@@ -73,17 +89,52 @@ const EmbedTemplateInstance = import_zod.z.lazy(
|
|
|
73
89
|
const WsEmbedTemplate = import_zod.z.lazy(
|
|
74
90
|
() => import_zod.z.array(import_zod.z.union([EmbedTemplateInstance, EmbedTemplateText]))
|
|
75
91
|
);
|
|
76
|
-
const createInstancesFromTemplate = (treeTemplate, instances, props, styleSourceSelections, styleSources, styles, defaultBreakpointId) => {
|
|
92
|
+
const createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceByRef, styleSourceSelections, styleSources, styles, defaultBreakpointId) => {
|
|
77
93
|
const parentChildren = [];
|
|
78
94
|
for (const item of treeTemplate) {
|
|
79
95
|
if (item.type === "instance") {
|
|
80
96
|
const instanceId = (0, import_nanoid.nanoid)();
|
|
81
97
|
if (item.props) {
|
|
82
98
|
for (const prop of item.props) {
|
|
99
|
+
const propId = (0, import_nanoid.nanoid)();
|
|
100
|
+
if (prop.dataSourceRef === void 0) {
|
|
101
|
+
props.push({ id: propId, instanceId, ...prop });
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
let dataSource = dataSourceByRef.get(prop.dataSourceRef.name);
|
|
105
|
+
if (dataSource === void 0) {
|
|
106
|
+
const id = (0, import_nanoid.nanoid)();
|
|
107
|
+
const { name: propName, dataSourceRef, ...rest } = prop;
|
|
108
|
+
if (dataSourceRef.type === "variable") {
|
|
109
|
+
dataSource = {
|
|
110
|
+
type: "variable",
|
|
111
|
+
id,
|
|
112
|
+
// the first instance where data source is appeared in becomes its scope
|
|
113
|
+
scopeInstanceId: instanceId,
|
|
114
|
+
name: dataSourceRef.name,
|
|
115
|
+
value: rest
|
|
116
|
+
};
|
|
117
|
+
dataSourceByRef.set(dataSourceRef.name, dataSource);
|
|
118
|
+
} else if (dataSourceRef.type === "expression") {
|
|
119
|
+
dataSource = {
|
|
120
|
+
type: "expression",
|
|
121
|
+
id,
|
|
122
|
+
scopeInstanceId: instanceId,
|
|
123
|
+
name: dataSourceRef.name,
|
|
124
|
+
code: dataSourceRef.code
|
|
125
|
+
};
|
|
126
|
+
dataSourceByRef.set(dataSourceRef.name, dataSource);
|
|
127
|
+
} else {
|
|
128
|
+
dataSourceRef;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
83
132
|
props.push({
|
|
84
|
-
id:
|
|
133
|
+
id: propId,
|
|
85
134
|
instanceId,
|
|
86
|
-
|
|
135
|
+
type: "dataSource",
|
|
136
|
+
name: prop.name,
|
|
137
|
+
value: dataSource.id
|
|
87
138
|
});
|
|
88
139
|
}
|
|
89
140
|
}
|
|
@@ -119,6 +170,7 @@ const createInstancesFromTemplate = (treeTemplate, instances, props, styleSource
|
|
|
119
170
|
item.children,
|
|
120
171
|
instances,
|
|
121
172
|
props,
|
|
173
|
+
dataSourceByRef,
|
|
122
174
|
styleSourceSelections,
|
|
123
175
|
styleSources,
|
|
124
176
|
styles,
|
|
@@ -141,6 +193,7 @@ const createInstancesFromTemplate = (treeTemplate, instances, props, styleSource
|
|
|
141
193
|
const generateDataFromEmbedTemplate = (treeTemplate, defaultBreakpointId) => {
|
|
142
194
|
const instances = [];
|
|
143
195
|
const props = [];
|
|
196
|
+
const dataSourceByRef = /* @__PURE__ */ new Map();
|
|
144
197
|
const styleSourceSelections = [];
|
|
145
198
|
const styleSources = [];
|
|
146
199
|
const styles = [];
|
|
@@ -148,15 +201,27 @@ const generateDataFromEmbedTemplate = (treeTemplate, defaultBreakpointId) => {
|
|
|
148
201
|
treeTemplate,
|
|
149
202
|
instances,
|
|
150
203
|
props,
|
|
204
|
+
dataSourceByRef,
|
|
151
205
|
styleSourceSelections,
|
|
152
206
|
styleSources,
|
|
153
207
|
styles,
|
|
154
208
|
defaultBreakpointId
|
|
155
209
|
);
|
|
210
|
+
const dataSources = [];
|
|
211
|
+
for (const dataSource of dataSourceByRef.values()) {
|
|
212
|
+
if (dataSource.type === "expression") {
|
|
213
|
+
dataSource.code = (0, import_expression.validateExpression)(dataSource.code, (ref) => {
|
|
214
|
+
const id = dataSourceByRef.get(ref)?.id ?? ref;
|
|
215
|
+
return (0, import_expression.encodeDataSourceVariable)(id);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
dataSources.push(dataSource);
|
|
219
|
+
}
|
|
156
220
|
return {
|
|
157
221
|
children,
|
|
158
222
|
instances,
|
|
159
223
|
props,
|
|
224
|
+
dataSources,
|
|
160
225
|
styleSourceSelections,
|
|
161
226
|
styleSources,
|
|
162
227
|
styles
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var expression_exports = {};
|
|
30
|
+
__export(expression_exports, {
|
|
31
|
+
decodeDataSourceVariable: () => decodeDataSourceVariable,
|
|
32
|
+
encodeDataSourceVariable: () => encodeDataSourceVariable,
|
|
33
|
+
executeExpressions: () => executeExpressions,
|
|
34
|
+
validateExpression: () => validateExpression
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(expression_exports);
|
|
37
|
+
var import_jsep = __toESM(require("jsep"), 1);
|
|
38
|
+
const generateCode = (node, failOnForbidden, transformIdentifier) => {
|
|
39
|
+
if (node.type === "Identifier") {
|
|
40
|
+
return transformIdentifier(node.name);
|
|
41
|
+
}
|
|
42
|
+
if (node.type === "MemberExpression") {
|
|
43
|
+
if (failOnForbidden) {
|
|
44
|
+
const object2 = generateCode(
|
|
45
|
+
node.object,
|
|
46
|
+
false,
|
|
47
|
+
transformIdentifier
|
|
48
|
+
);
|
|
49
|
+
const property2 = generateCode(
|
|
50
|
+
node.property,
|
|
51
|
+
false,
|
|
52
|
+
transformIdentifier
|
|
53
|
+
);
|
|
54
|
+
throw Error(`Cannot access "${property2}" of "${object2}"`);
|
|
55
|
+
}
|
|
56
|
+
const object = generateCode(
|
|
57
|
+
node.object,
|
|
58
|
+
failOnForbidden,
|
|
59
|
+
transformIdentifier
|
|
60
|
+
);
|
|
61
|
+
const property = generateCode(
|
|
62
|
+
node.property,
|
|
63
|
+
failOnForbidden,
|
|
64
|
+
transformIdentifier
|
|
65
|
+
);
|
|
66
|
+
return `${object}.${property}`;
|
|
67
|
+
}
|
|
68
|
+
if (node.type === "Literal") {
|
|
69
|
+
return node.raw;
|
|
70
|
+
}
|
|
71
|
+
if (node.type === "UnaryExpression") {
|
|
72
|
+
const arg = generateCode(
|
|
73
|
+
node.argument,
|
|
74
|
+
failOnForbidden,
|
|
75
|
+
transformIdentifier
|
|
76
|
+
);
|
|
77
|
+
return `${node.operator}${arg}`;
|
|
78
|
+
}
|
|
79
|
+
if (node.type === "BinaryExpression") {
|
|
80
|
+
const left = generateCode(
|
|
81
|
+
node.left,
|
|
82
|
+
failOnForbidden,
|
|
83
|
+
transformIdentifier
|
|
84
|
+
);
|
|
85
|
+
const right = generateCode(
|
|
86
|
+
node.right,
|
|
87
|
+
failOnForbidden,
|
|
88
|
+
transformIdentifier
|
|
89
|
+
);
|
|
90
|
+
return `${left} ${node.operator} ${right}`;
|
|
91
|
+
}
|
|
92
|
+
if (node.type === "ArrayExpression") {
|
|
93
|
+
const elements = node.elements.map(
|
|
94
|
+
(element) => generateCode(element, failOnForbidden, transformIdentifier)
|
|
95
|
+
);
|
|
96
|
+
return `[${elements.join(", ")}]`;
|
|
97
|
+
}
|
|
98
|
+
if (node.type === "CallExpression") {
|
|
99
|
+
if (failOnForbidden) {
|
|
100
|
+
const callee2 = generateCode(
|
|
101
|
+
node.callee,
|
|
102
|
+
false,
|
|
103
|
+
transformIdentifier
|
|
104
|
+
);
|
|
105
|
+
throw Error(`Cannot call "${callee2}"`);
|
|
106
|
+
}
|
|
107
|
+
const callee = generateCode(
|
|
108
|
+
node.callee,
|
|
109
|
+
failOnForbidden,
|
|
110
|
+
transformIdentifier
|
|
111
|
+
);
|
|
112
|
+
const args = node.arguments.map(
|
|
113
|
+
(arg) => generateCode(arg, failOnForbidden, transformIdentifier)
|
|
114
|
+
);
|
|
115
|
+
return `${callee}(${args.join(", ")})`;
|
|
116
|
+
}
|
|
117
|
+
if (node.type === "ThisExpression") {
|
|
118
|
+
if (failOnForbidden) {
|
|
119
|
+
throw Error(`"this" is not supported`);
|
|
120
|
+
}
|
|
121
|
+
return "this";
|
|
122
|
+
}
|
|
123
|
+
if (node.type === "ConditionalExpression") {
|
|
124
|
+
throw Error("Ternary operator is not supported");
|
|
125
|
+
}
|
|
126
|
+
if (node.type === "Compound") {
|
|
127
|
+
throw Error("Cannot use multiple expressions");
|
|
128
|
+
}
|
|
129
|
+
node;
|
|
130
|
+
return "";
|
|
131
|
+
};
|
|
132
|
+
const validateExpression = (code, transformIdentifier = (id) => id) => {
|
|
133
|
+
const expression = (0, import_jsep.default)(code);
|
|
134
|
+
return generateCode(expression, true, transformIdentifier);
|
|
135
|
+
};
|
|
136
|
+
const executeExpressions = (variables, expressions) => {
|
|
137
|
+
const depsById = /* @__PURE__ */ new Map();
|
|
138
|
+
for (const [id, code] of expressions) {
|
|
139
|
+
const deps = /* @__PURE__ */ new Set();
|
|
140
|
+
validateExpression(code, (identifier) => {
|
|
141
|
+
if (variables.has(identifier) || expressions.has(identifier)) {
|
|
142
|
+
deps.add(identifier);
|
|
143
|
+
return identifier;
|
|
144
|
+
}
|
|
145
|
+
throw Error(`Unknown dependency "${identifier}"`);
|
|
146
|
+
});
|
|
147
|
+
depsById.set(id, deps);
|
|
148
|
+
}
|
|
149
|
+
const sortedExpressions = Array.from(expressions.keys()).sort(
|
|
150
|
+
(left, right) => {
|
|
151
|
+
if (depsById.get(left)?.has(right)) {
|
|
152
|
+
return 1;
|
|
153
|
+
}
|
|
154
|
+
if (depsById.get(right)?.has(left)) {
|
|
155
|
+
return -1;
|
|
156
|
+
}
|
|
157
|
+
return 0;
|
|
158
|
+
}
|
|
159
|
+
);
|
|
160
|
+
let header = "";
|
|
161
|
+
for (const [id, value] of variables) {
|
|
162
|
+
header += `const ${id} = ${JSON.stringify(value)};
|
|
163
|
+
`;
|
|
164
|
+
}
|
|
165
|
+
const values = /* @__PURE__ */ new Map();
|
|
166
|
+
for (const id of sortedExpressions) {
|
|
167
|
+
const code = expressions.get(id);
|
|
168
|
+
if (code === void 0) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
const executeFn = new Function(`${header}
|
|
172
|
+
return (${code});`);
|
|
173
|
+
const value = executeFn();
|
|
174
|
+
header += `const ${id} = ${JSON.stringify(value)};
|
|
175
|
+
`;
|
|
176
|
+
values.set(id, value);
|
|
177
|
+
}
|
|
178
|
+
return values;
|
|
179
|
+
};
|
|
180
|
+
const dataSourceVariablePrefix = "$ws$dataSource$";
|
|
181
|
+
const encodeDataSourceVariable = (id) => {
|
|
182
|
+
const encoded = id.replaceAll("-", "__DASH__");
|
|
183
|
+
return `${dataSourceVariablePrefix}${encoded}`;
|
|
184
|
+
};
|
|
185
|
+
const decodeDataSourceVariable = (name) => {
|
|
186
|
+
if (name.startsWith(dataSourceVariablePrefix)) {
|
|
187
|
+
const encoded = name.slice(dataSourceVariablePrefix.length);
|
|
188
|
+
return encoded.replaceAll("__DASH__", "-");
|
|
189
|
+
}
|
|
190
|
+
return;
|
|
191
|
+
};
|
package/lib/cjs/index.js
CHANGED
|
@@ -21,11 +21,16 @@ var src_exports = {};
|
|
|
21
21
|
__export(src_exports, {
|
|
22
22
|
ReactSdkContext: () => import_context.ReactSdkContext,
|
|
23
23
|
componentCategories: () => import_component_meta.componentCategories,
|
|
24
|
+
decodeDataSourceVariable: () => import_expression.decodeDataSourceVariable,
|
|
24
25
|
defaultStates: () => import_component_meta.defaultStates,
|
|
26
|
+
encodeDataSourceVariable: () => import_expression.encodeDataSourceVariable,
|
|
27
|
+
executeExpressions: () => import_expression.executeExpressions,
|
|
25
28
|
getInstanceIdFromComponentProps: () => import_props.getInstanceIdFromComponentProps,
|
|
26
29
|
stateCategories: () => import_component_meta.stateCategories,
|
|
30
|
+
useInstanceProps: () => import_props.useInstanceProps,
|
|
27
31
|
usePropAsset: () => import_props.usePropAsset,
|
|
28
|
-
usePropUrl: () => import_props.usePropUrl
|
|
32
|
+
usePropUrl: () => import_props.usePropUrl,
|
|
33
|
+
validateExpression: () => import_expression.validateExpression
|
|
29
34
|
});
|
|
30
35
|
module.exports = __toCommonJS(src_exports);
|
|
31
36
|
__reExport(src_exports, require("./css"), module.exports);
|
|
@@ -37,3 +42,4 @@ var import_component_meta = require("./components/component-meta");
|
|
|
37
42
|
__reExport(src_exports, require("./embed-template"), module.exports);
|
|
38
43
|
var import_props = require("./props");
|
|
39
44
|
var import_context = require("./context");
|
|
45
|
+
var import_expression = require("./expression");
|
package/lib/cjs/props.js
CHANGED
|
@@ -44,17 +44,35 @@ const getPropsByInstanceId = (props) => {
|
|
|
44
44
|
return propsByInstanceId;
|
|
45
45
|
};
|
|
46
46
|
const useInstanceProps = (instanceId) => {
|
|
47
|
-
const { propsByInstanceIdStore } = (0, import_react.useContext)(import_context.ReactSdkContext);
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
const { propsByInstanceIdStore, dataSourceValuesStore } = (0, import_react.useContext)(import_context.ReactSdkContext);
|
|
48
|
+
const instancePropsObjectStore = (0, import_react.useMemo)(() => {
|
|
49
|
+
return (0, import_nanostores.computed)(
|
|
50
|
+
[propsByInstanceIdStore, dataSourceValuesStore],
|
|
51
|
+
(propsByInstanceId, dataSourceValues) => {
|
|
52
|
+
const instancePropsObject2 = {};
|
|
53
|
+
const instanceProps = propsByInstanceId.get(instanceId);
|
|
54
|
+
if (instanceProps === void 0) {
|
|
55
|
+
return instancePropsObject2;
|
|
56
|
+
}
|
|
57
|
+
for (const prop of instanceProps) {
|
|
58
|
+
if (prop.type === "asset" || prop.type === "page") {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (prop.type === "dataSource") {
|
|
62
|
+
const dataSourceId = prop.value;
|
|
63
|
+
const value = dataSourceValues.get(dataSourceId);
|
|
64
|
+
if (value !== void 0) {
|
|
65
|
+
instancePropsObject2[prop.name] = value;
|
|
66
|
+
}
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
instancePropsObject2[prop.name] = prop.value;
|
|
70
|
+
}
|
|
71
|
+
return instancePropsObject2;
|
|
55
72
|
}
|
|
56
|
-
|
|
57
|
-
}
|
|
73
|
+
);
|
|
74
|
+
}, [propsByInstanceIdStore, dataSourceValuesStore, instanceId]);
|
|
75
|
+
const instancePropsObject = (0, import_react2.useStore)(instancePropsObjectStore);
|
|
58
76
|
return instancePropsObject;
|
|
59
77
|
};
|
|
60
78
|
const usePropAsset = (instanceId, name) => {
|
|
@@ -34,6 +34,8 @@ const createElementsTree = ({
|
|
|
34
34
|
propsByInstanceIdStore,
|
|
35
35
|
assetsStore,
|
|
36
36
|
pagesStore,
|
|
37
|
+
dataSourceValuesStore,
|
|
38
|
+
onDataSourceUpdate,
|
|
37
39
|
Component,
|
|
38
40
|
components
|
|
39
41
|
}) => {
|
|
@@ -69,9 +71,20 @@ const createElementsTree = ({
|
|
|
69
71
|
propsByInstanceIdStore,
|
|
70
72
|
assetsStore,
|
|
71
73
|
pagesStore,
|
|
74
|
+
dataSourceValuesStore,
|
|
72
75
|
renderer,
|
|
73
76
|
imageBaseUrl,
|
|
74
|
-
assetBaseUrl
|
|
77
|
+
assetBaseUrl,
|
|
78
|
+
setDataSourceValue: (instanceId, propName, value) => {
|
|
79
|
+
const propsByInstanceId = propsByInstanceIdStore.get();
|
|
80
|
+
const props = propsByInstanceId.get(instanceId);
|
|
81
|
+
const prop = props?.find((prop2) => prop2.name === propName);
|
|
82
|
+
if (prop?.type !== "dataSource") {
|
|
83
|
+
throw Error(`${propName} is not data source`);
|
|
84
|
+
}
|
|
85
|
+
const dataSourceId = prop.value;
|
|
86
|
+
onDataSourceUpdate(dataSourceId, value);
|
|
87
|
+
}
|
|
75
88
|
},
|
|
76
89
|
children: root
|
|
77
90
|
}
|
package/lib/cjs/tree/root.js
CHANGED
|
@@ -21,15 +21,64 @@ __export(root_exports, {
|
|
|
21
21
|
InstanceRoot: () => InstanceRoot
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(root_exports);
|
|
24
|
+
var import_react = require("react");
|
|
24
25
|
var import_nanostores = require("nanostores");
|
|
25
26
|
var import_create_elements_tree = require("./create-elements-tree");
|
|
26
27
|
var import_webstudio_component = require("./webstudio-component");
|
|
27
28
|
var import_props = require("../props");
|
|
29
|
+
var import_expression = require("../expression");
|
|
30
|
+
const computeExpressions = (dataSources, dataSourceValues) => {
|
|
31
|
+
const outputValues = /* @__PURE__ */ new Map();
|
|
32
|
+
const variables = /* @__PURE__ */ new Map();
|
|
33
|
+
const expressions = /* @__PURE__ */ new Map();
|
|
34
|
+
for (const [dataSourceId, dataSource] of dataSources) {
|
|
35
|
+
const name = (0, import_expression.encodeDataSourceVariable)(dataSourceId);
|
|
36
|
+
if (dataSource.type === "variable") {
|
|
37
|
+
const value = dataSourceValues.get(dataSourceId) ?? dataSource.value.value;
|
|
38
|
+
variables.set(name, value);
|
|
39
|
+
outputValues.set(dataSourceId, value);
|
|
40
|
+
}
|
|
41
|
+
if (dataSource.type === "expression") {
|
|
42
|
+
expressions.set(name, dataSource.code);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const outputVariables = (0, import_expression.executeExpressions)(variables, expressions);
|
|
47
|
+
for (const [name, value] of outputVariables) {
|
|
48
|
+
const id = (0, import_expression.decodeDataSourceVariable)(name);
|
|
49
|
+
if (id !== void 0) {
|
|
50
|
+
outputValues.set(id, value);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error(error);
|
|
55
|
+
}
|
|
56
|
+
return outputValues;
|
|
57
|
+
};
|
|
28
58
|
const InstanceRoot = ({
|
|
29
59
|
data,
|
|
30
60
|
Component,
|
|
31
61
|
components
|
|
32
62
|
}) => {
|
|
63
|
+
const dataSourceVariablesStoreRef = (0, import_react.useRef)(void 0);
|
|
64
|
+
if (dataSourceVariablesStoreRef.current === void 0) {
|
|
65
|
+
const dataSourceVariables = /* @__PURE__ */ new Map();
|
|
66
|
+
for (const [dataSourceId, dataSource] of data.build.dataSources) {
|
|
67
|
+
dataSourceVariables.set(dataSourceId, dataSource);
|
|
68
|
+
}
|
|
69
|
+
dataSourceVariablesStoreRef.current = (0, import_nanostores.atom)(dataSourceVariables);
|
|
70
|
+
}
|
|
71
|
+
const dataSourceVariablesStore = dataSourceVariablesStoreRef.current;
|
|
72
|
+
const dataSourceValuesStoreRef = (0, import_react.useRef)(void 0);
|
|
73
|
+
if (dataSourceValuesStoreRef.current === void 0) {
|
|
74
|
+
dataSourceValuesStoreRef.current = (0, import_nanostores.computed)(
|
|
75
|
+
dataSourceVariablesStore,
|
|
76
|
+
(dataSourceVariables) => {
|
|
77
|
+
return computeExpressions(data.build.dataSources, dataSourceVariables);
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
const dataSourceValuesStore = dataSourceValuesStoreRef.current;
|
|
33
82
|
return (0, import_create_elements_tree.createElementsTree)({
|
|
34
83
|
imageBaseUrl: data.params?.imageBaseUrl ?? "/",
|
|
35
84
|
assetBaseUrl: data.params?.assetBaseUrl ?? "/",
|
|
@@ -40,6 +89,12 @@ const InstanceRoot = ({
|
|
|
40
89
|
),
|
|
41
90
|
assetsStore: (0, import_nanostores.atom)(new Map(data.assets.map((asset) => [asset.id, asset]))),
|
|
42
91
|
pagesStore: (0, import_nanostores.atom)(new Map(data.pages.map((page) => [page.id, page]))),
|
|
92
|
+
dataSourceValuesStore,
|
|
93
|
+
onDataSourceUpdate: (dataSourceId, value) => {
|
|
94
|
+
const dataSourceVariables = new Map(dataSourceVariablesStore.get());
|
|
95
|
+
dataSourceVariables.set(dataSourceId, value);
|
|
96
|
+
dataSourceVariablesStore.set(dataSourceVariables);
|
|
97
|
+
},
|
|
43
98
|
Component: Component ?? import_webstudio_component.WebstudioComponent,
|
|
44
99
|
components
|
|
45
100
|
});
|
|
@@ -22,7 +22,8 @@ __export(webstudio_component_exports, {
|
|
|
22
22
|
collapsedAttribute: () => collapsedAttribute,
|
|
23
23
|
componentAttribute: () => componentAttribute,
|
|
24
24
|
idAttribute: () => idAttribute,
|
|
25
|
-
renderWebstudioComponentChildren: () => renderWebstudioComponentChildren
|
|
25
|
+
renderWebstudioComponentChildren: () => renderWebstudioComponentChildren,
|
|
26
|
+
showAttribute: () => showAttribute
|
|
26
27
|
});
|
|
27
28
|
module.exports = __toCommonJS(webstudio_component_exports);
|
|
28
29
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -50,13 +51,18 @@ const WebstudioComponent = ({
|
|
|
50
51
|
components,
|
|
51
52
|
...rest
|
|
52
53
|
}) => {
|
|
53
|
-
const instanceProps = (0, import_props.useInstanceProps)(
|
|
54
|
+
const { [showAttribute]: show = true, ...instanceProps } = (0, import_props.useInstanceProps)(
|
|
55
|
+
instance.id
|
|
56
|
+
);
|
|
54
57
|
const props = {
|
|
55
58
|
...instanceProps,
|
|
56
59
|
...rest,
|
|
57
60
|
[idAttribute]: instance.id,
|
|
58
61
|
[componentAttribute]: instance.component
|
|
59
62
|
};
|
|
63
|
+
if (show === false) {
|
|
64
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {});
|
|
65
|
+
}
|
|
60
66
|
const Component = components.get(instance.component);
|
|
61
67
|
if (Component === void 0) {
|
|
62
68
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {});
|
|
@@ -65,4 +71,5 @@ const WebstudioComponent = ({
|
|
|
65
71
|
};
|
|
66
72
|
const idAttribute = "data-ws-id";
|
|
67
73
|
const componentAttribute = "data-ws-component";
|
|
74
|
+
const showAttribute = "data-ws-show";
|
|
68
75
|
const collapsedAttribute = "data-ws-collapsed";
|
|
@@ -37,6 +37,7 @@ const WsComponentMeta = z.object({
|
|
|
37
37
|
invalidAncestors: z.optional(z.array(z.string())),
|
|
38
38
|
stylable: z.optional(z.boolean()),
|
|
39
39
|
label: z.string(),
|
|
40
|
+
description: z.string().optional(),
|
|
40
41
|
icon: z.string(),
|
|
41
42
|
presetStyle: z.optional(z.record(z.string(), EmbedTemplateStyleDecl)),
|
|
42
43
|
states: z.optional(z.array(ComponentState)),
|
package/lib/context.js
CHANGED
|
@@ -5,7 +5,11 @@ const ReactSdkContext = createContext({
|
|
|
5
5
|
assetBaseUrl: "/",
|
|
6
6
|
propsByInstanceIdStore: atom(/* @__PURE__ */ new Map()),
|
|
7
7
|
assetsStore: atom(/* @__PURE__ */ new Map()),
|
|
8
|
-
pagesStore: atom(/* @__PURE__ */ new Map())
|
|
8
|
+
pagesStore: atom(/* @__PURE__ */ new Map()),
|
|
9
|
+
dataSourceValuesStore: atom(/* @__PURE__ */ new Map()),
|
|
10
|
+
setDataSourceValue: () => {
|
|
11
|
+
throw Error("React SDK setDataSourceValue is not implemented");
|
|
12
|
+
}
|
|
9
13
|
});
|
|
10
14
|
export {
|
|
11
15
|
ReactSdkContext
|
package/lib/css/global-rules.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getFontFaces } from "@webstudio-is/fonts";
|
|
2
2
|
const addGlobalRules = (engine, { assets, assetBaseUrl }) => {
|
|
3
|
-
engine.addPlaintextRule("html {margin: 0; height: 100%}");
|
|
3
|
+
engine.addPlaintextRule("html {margin: 0; display: grid; min-height: 100%}");
|
|
4
4
|
const fontAssets = [];
|
|
5
5
|
for (const asset of assets.values()) {
|
|
6
6
|
if (asset?.type === "font") {
|