@webstudio-is/react-sdk 0.79.0 → 0.80.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/context.js +8 -2
- package/lib/cjs/css/normalize.js +1 -1
- package/lib/cjs/embed-template.js +45 -16
- package/lib/cjs/expression.js +137 -22
- package/lib/cjs/index.js +6 -2
- package/lib/cjs/props.js +32 -2
- package/lib/cjs/tree/create-elements-tree.js +7 -2
- package/lib/cjs/tree/root.js +15 -7
- package/lib/context.js +8 -2
- package/lib/css/normalize.js +1 -1
- package/lib/embed-template.js +45 -16
- package/lib/expression.js +137 -22
- package/lib/index.js +13 -5
- package/lib/props.js +32 -2
- package/lib/tree/create-elements-tree.js +10 -3
- package/lib/tree/root.js +16 -8
- package/lib/types/components/component-meta.d.ts +30 -0
- package/lib/types/context.d.ts +5 -2
- package/lib/types/embed-template.d.ts +38 -0
- package/lib/types/expression.d.ts +12 -4
- package/lib/types/index.d.ts +1 -1
- package/lib/types/props.d.ts +10 -0
- package/lib/types/tree/create-elements-tree.d.ts +6 -5
- package/lib/types/tree/root.d.ts +5 -5
- package/package.json +17 -16
- package/src/context.tsx +17 -4
- package/src/css/normalize.ts +1 -1
- package/src/embed-template.test.ts +84 -4
- package/src/embed-template.ts +51 -18
- package/src/expression.test.ts +106 -12
- package/src/expression.ts +157 -26
- package/src/index.ts +6 -2
- package/src/props.ts +33 -3
- package/src/tree/create-elements-tree.tsx +19 -10
- package/src/tree/root.ts +24 -13
package/lib/cjs/context.js
CHANGED
|
@@ -30,7 +30,13 @@ const ReactSdkContext = (0, import_react.createContext)({
|
|
|
30
30
|
assetsStore: (0, import_nanostores.atom)(/* @__PURE__ */ new Map()),
|
|
31
31
|
pagesStore: (0, import_nanostores.atom)(/* @__PURE__ */ new Map()),
|
|
32
32
|
dataSourceValuesStore: (0, import_nanostores.atom)(/* @__PURE__ */ new Map()),
|
|
33
|
-
|
|
34
|
-
throw Error("React SDK
|
|
33
|
+
executeEffectfulExpression: () => {
|
|
34
|
+
throw Error("React SDK executeEffectfulExpression is not implemented");
|
|
35
|
+
},
|
|
36
|
+
setDataSourceValues: () => {
|
|
37
|
+
throw Error("React SDK setBoundDataSourceValue is not implemented");
|
|
38
|
+
},
|
|
39
|
+
setBoundDataSourceValue: () => {
|
|
40
|
+
throw Error("React SDK setBoundDataSourceValue is not implemented");
|
|
35
41
|
}
|
|
36
42
|
});
|
package/lib/cjs/css/normalize.js
CHANGED
|
@@ -32,11 +32,12 @@ const EmbedTemplateText = import_zod.z.object({
|
|
|
32
32
|
type: import_zod.z.literal("text"),
|
|
33
33
|
value: import_zod.z.string()
|
|
34
34
|
});
|
|
35
|
+
const DataSourceVariableRef = import_zod.z.object({
|
|
36
|
+
type: import_zod.z.literal("variable"),
|
|
37
|
+
name: import_zod.z.string()
|
|
38
|
+
});
|
|
35
39
|
const DataSourceRef = import_zod.z.union([
|
|
36
|
-
|
|
37
|
-
type: import_zod.z.literal("variable"),
|
|
38
|
-
name: import_zod.z.string()
|
|
39
|
-
}),
|
|
40
|
+
DataSourceVariableRef,
|
|
40
41
|
import_zod.z.object({
|
|
41
42
|
type: import_zod.z.literal("expression"),
|
|
42
43
|
name: import_zod.z.string(),
|
|
@@ -67,6 +68,16 @@ const EmbedTemplateProp = import_zod.z.union([
|
|
|
67
68
|
name: import_zod.z.string(),
|
|
68
69
|
dataSourceRef: import_zod.z.optional(DataSourceRef),
|
|
69
70
|
value: import_zod.z.array(import_zod.z.string())
|
|
71
|
+
}),
|
|
72
|
+
import_zod.z.object({
|
|
73
|
+
type: import_zod.z.literal("action"),
|
|
74
|
+
name: import_zod.z.string(),
|
|
75
|
+
value: import_zod.z.array(
|
|
76
|
+
import_zod.z.object({
|
|
77
|
+
type: import_zod.z.literal("execute"),
|
|
78
|
+
code: import_zod.z.string()
|
|
79
|
+
})
|
|
80
|
+
)
|
|
70
81
|
})
|
|
71
82
|
]);
|
|
72
83
|
const EmbedTemplateStyleDeclRaw = import_zod.z.object({
|
|
@@ -97,6 +108,28 @@ const createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceB
|
|
|
97
108
|
if (item.props) {
|
|
98
109
|
for (const prop of item.props) {
|
|
99
110
|
const propId = (0, import_nanoid.nanoid)();
|
|
111
|
+
if (prop.type === "action") {
|
|
112
|
+
props.push({
|
|
113
|
+
id: propId,
|
|
114
|
+
instanceId,
|
|
115
|
+
type: "action",
|
|
116
|
+
name: prop.name,
|
|
117
|
+
value: prop.value.map((value) => {
|
|
118
|
+
return {
|
|
119
|
+
type: "execute",
|
|
120
|
+
// replace all references with variable names
|
|
121
|
+
code: (0, import_expression.validateExpression)(value.code, {
|
|
122
|
+
effectful: true,
|
|
123
|
+
transformIdentifier: (ref) => {
|
|
124
|
+
const id = dataSourceByRef.get(ref)?.id ?? ref;
|
|
125
|
+
return (0, import_expression.encodeDataSourceVariable)(id);
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
};
|
|
129
|
+
})
|
|
130
|
+
});
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
100
133
|
if (prop.dataSourceRef === void 0) {
|
|
101
134
|
props.push({ id: propId, instanceId, ...prop });
|
|
102
135
|
continue;
|
|
@@ -121,7 +154,13 @@ const createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceB
|
|
|
121
154
|
id,
|
|
122
155
|
scopeInstanceId: instanceId,
|
|
123
156
|
name: dataSourceRef.name,
|
|
124
|
-
|
|
157
|
+
// replace all references with variable names
|
|
158
|
+
code: (0, import_expression.validateExpression)(dataSourceRef.code, {
|
|
159
|
+
transformIdentifier: (ref) => {
|
|
160
|
+
const id2 = dataSourceByRef.get(ref)?.id ?? ref;
|
|
161
|
+
return (0, import_expression.encodeDataSourceVariable)(id2);
|
|
162
|
+
}
|
|
163
|
+
})
|
|
125
164
|
};
|
|
126
165
|
dataSourceByRef.set(dataSourceRef.name, dataSource);
|
|
127
166
|
} else {
|
|
@@ -207,21 +246,11 @@ const generateDataFromEmbedTemplate = (treeTemplate, defaultBreakpointId) => {
|
|
|
207
246
|
styles,
|
|
208
247
|
defaultBreakpointId
|
|
209
248
|
);
|
|
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
|
-
}
|
|
220
249
|
return {
|
|
221
250
|
children,
|
|
222
251
|
instances,
|
|
223
252
|
props,
|
|
224
|
-
dataSources,
|
|
253
|
+
dataSources: Array.from(dataSourceByRef.values()),
|
|
225
254
|
styleSourceSelections,
|
|
226
255
|
styleSources,
|
|
227
256
|
styles
|
package/lib/cjs/expression.js
CHANGED
|
@@ -29,27 +29,35 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
29
29
|
var expression_exports = {};
|
|
30
30
|
__export(expression_exports, {
|
|
31
31
|
decodeDataSourceVariable: () => decodeDataSourceVariable,
|
|
32
|
+
decodeVariablesMap: () => decodeVariablesMap,
|
|
32
33
|
encodeDataSourceVariable: () => encodeDataSourceVariable,
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
encodeVariablesMap: () => encodeVariablesMap,
|
|
35
|
+
executeComputingExpressions: () => executeComputingExpressions,
|
|
36
|
+
executeEffectfulExpression: () => executeEffectfulExpression,
|
|
37
|
+
generateComputingExpressions: () => generateComputingExpressions,
|
|
38
|
+
generateEffectfulExpression: () => generateEffectfulExpression,
|
|
35
39
|
validateExpression: () => validateExpression
|
|
36
40
|
});
|
|
37
41
|
module.exports = __toCommonJS(expression_exports);
|
|
38
42
|
var import_jsep = __toESM(require("jsep"), 1);
|
|
39
|
-
|
|
43
|
+
var import_assignment = __toESM(require("@jsep-plugin/assignment"), 1);
|
|
44
|
+
import_jsep.default.plugins.register(import_assignment.default);
|
|
45
|
+
const generateCode = (node, failOnForbidden, effectful, transformIdentifier) => {
|
|
40
46
|
if (node.type === "Identifier") {
|
|
41
|
-
return transformIdentifier(node.name);
|
|
47
|
+
return transformIdentifier(node.name, false);
|
|
42
48
|
}
|
|
43
49
|
if (node.type === "MemberExpression") {
|
|
44
50
|
if (failOnForbidden) {
|
|
45
51
|
const object2 = generateCode(
|
|
46
52
|
node.object,
|
|
47
53
|
false,
|
|
54
|
+
effectful,
|
|
48
55
|
transformIdentifier
|
|
49
56
|
);
|
|
50
57
|
const property2 = generateCode(
|
|
51
58
|
node.property,
|
|
52
59
|
false,
|
|
60
|
+
effectful,
|
|
53
61
|
transformIdentifier
|
|
54
62
|
);
|
|
55
63
|
throw Error(`Cannot access "${property2}" of "${object2}"`);
|
|
@@ -57,11 +65,13 @@ const generateCode = (node, failOnForbidden, transformIdentifier) => {
|
|
|
57
65
|
const object = generateCode(
|
|
58
66
|
node.object,
|
|
59
67
|
failOnForbidden,
|
|
68
|
+
effectful,
|
|
60
69
|
transformIdentifier
|
|
61
70
|
);
|
|
62
71
|
const property = generateCode(
|
|
63
72
|
node.property,
|
|
64
73
|
failOnForbidden,
|
|
74
|
+
effectful,
|
|
65
75
|
transformIdentifier
|
|
66
76
|
);
|
|
67
77
|
return `${object}.${property}`;
|
|
@@ -73,6 +83,7 @@ const generateCode = (node, failOnForbidden, transformIdentifier) => {
|
|
|
73
83
|
const arg = generateCode(
|
|
74
84
|
node.argument,
|
|
75
85
|
failOnForbidden,
|
|
86
|
+
effectful,
|
|
76
87
|
transformIdentifier
|
|
77
88
|
);
|
|
78
89
|
return `${node.operator}${arg}`;
|
|
@@ -81,18 +92,25 @@ const generateCode = (node, failOnForbidden, transformIdentifier) => {
|
|
|
81
92
|
const left = generateCode(
|
|
82
93
|
node.left,
|
|
83
94
|
failOnForbidden,
|
|
95
|
+
effectful,
|
|
84
96
|
transformIdentifier
|
|
85
97
|
);
|
|
86
98
|
const right = generateCode(
|
|
87
99
|
node.right,
|
|
88
100
|
failOnForbidden,
|
|
101
|
+
effectful,
|
|
89
102
|
transformIdentifier
|
|
90
103
|
);
|
|
91
104
|
return `${left} ${node.operator} ${right}`;
|
|
92
105
|
}
|
|
93
106
|
if (node.type === "ArrayExpression") {
|
|
94
107
|
const elements = node.elements.map(
|
|
95
|
-
(element) => generateCode(
|
|
108
|
+
(element) => generateCode(
|
|
109
|
+
element,
|
|
110
|
+
failOnForbidden,
|
|
111
|
+
effectful,
|
|
112
|
+
transformIdentifier
|
|
113
|
+
)
|
|
96
114
|
);
|
|
97
115
|
return `[${elements.join(", ")}]`;
|
|
98
116
|
}
|
|
@@ -101,6 +119,7 @@ const generateCode = (node, failOnForbidden, transformIdentifier) => {
|
|
|
101
119
|
const callee2 = generateCode(
|
|
102
120
|
node.callee,
|
|
103
121
|
false,
|
|
122
|
+
effectful,
|
|
104
123
|
transformIdentifier
|
|
105
124
|
);
|
|
106
125
|
throw Error(`Cannot call "${callee2}"`);
|
|
@@ -108,10 +127,11 @@ const generateCode = (node, failOnForbidden, transformIdentifier) => {
|
|
|
108
127
|
const callee = generateCode(
|
|
109
128
|
node.callee,
|
|
110
129
|
failOnForbidden,
|
|
130
|
+
effectful,
|
|
111
131
|
transformIdentifier
|
|
112
132
|
);
|
|
113
133
|
const args = node.arguments.map(
|
|
114
|
-
(arg) => generateCode(arg, failOnForbidden, transformIdentifier)
|
|
134
|
+
(arg) => generateCode(arg, failOnForbidden, effectful, transformIdentifier)
|
|
115
135
|
);
|
|
116
136
|
return `${callee}(${args.join(", ")})`;
|
|
117
137
|
}
|
|
@@ -127,12 +147,38 @@ const generateCode = (node, failOnForbidden, transformIdentifier) => {
|
|
|
127
147
|
if (node.type === "Compound") {
|
|
128
148
|
throw Error("Cannot use multiple expressions");
|
|
129
149
|
}
|
|
150
|
+
if (node.type === "AssignmentExpression") {
|
|
151
|
+
if (node.operator !== "=") {
|
|
152
|
+
throw Error(`Only "=" assignment operator is supported`);
|
|
153
|
+
}
|
|
154
|
+
if (effectful === false) {
|
|
155
|
+
throw Error(`Cannot use assignment in this expression`);
|
|
156
|
+
}
|
|
157
|
+
const left = generateCode(
|
|
158
|
+
node.left,
|
|
159
|
+
failOnForbidden,
|
|
160
|
+
effectful,
|
|
161
|
+
// override and mark all identifiers inside of left expression as assignee
|
|
162
|
+
(id) => transformIdentifier(id, true)
|
|
163
|
+
);
|
|
164
|
+
const right = generateCode(
|
|
165
|
+
node.right,
|
|
166
|
+
failOnForbidden,
|
|
167
|
+
effectful,
|
|
168
|
+
transformIdentifier
|
|
169
|
+
);
|
|
170
|
+
return `${left} ${node.operator} ${right}`;
|
|
171
|
+
}
|
|
172
|
+
if (node.type === "UpdateExpression") {
|
|
173
|
+
throw Error(`"${node.operator}" operator is not supported`);
|
|
174
|
+
}
|
|
130
175
|
node;
|
|
131
176
|
return "";
|
|
132
177
|
};
|
|
133
|
-
const validateExpression = (code,
|
|
178
|
+
const validateExpression = (code, options) => {
|
|
179
|
+
const { effectful = false, transformIdentifier = (id) => id } = options ?? {};
|
|
134
180
|
const expression = (0, import_jsep.default)(code);
|
|
135
|
-
return generateCode(expression, true, transformIdentifier);
|
|
181
|
+
return generateCode(expression, true, effectful, transformIdentifier);
|
|
136
182
|
};
|
|
137
183
|
const sortTopologically = (list, depsById, explored = /* @__PURE__ */ new Set(), sorted = []) => {
|
|
138
184
|
for (const id of list) {
|
|
@@ -148,19 +194,23 @@ const sortTopologically = (list, depsById, explored = /* @__PURE__ */ new Set(),
|
|
|
148
194
|
}
|
|
149
195
|
return sorted;
|
|
150
196
|
};
|
|
151
|
-
const
|
|
197
|
+
const generateComputingExpressions = (expressions, allowedVariables) => {
|
|
152
198
|
const depsById = /* @__PURE__ */ new Map();
|
|
199
|
+
const inputVariables = /* @__PURE__ */ new Set();
|
|
153
200
|
for (const [id, code] of expressions) {
|
|
154
201
|
const deps = /* @__PURE__ */ new Set();
|
|
155
|
-
validateExpression(code,
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
202
|
+
validateExpression(code, {
|
|
203
|
+
transformIdentifier: (identifier) => {
|
|
204
|
+
if (allowedVariables.has(identifier)) {
|
|
205
|
+
inputVariables.add(identifier);
|
|
206
|
+
return identifier;
|
|
207
|
+
}
|
|
208
|
+
if (expressions.has(identifier)) {
|
|
209
|
+
deps.add(identifier);
|
|
210
|
+
return identifier;
|
|
211
|
+
}
|
|
212
|
+
throw Error(`Unknown dependency "${identifier}"`);
|
|
162
213
|
}
|
|
163
|
-
throw Error(`Unknown dependency "${identifier}"`);
|
|
164
214
|
});
|
|
165
215
|
depsById.set(id, deps);
|
|
166
216
|
}
|
|
@@ -169,7 +219,7 @@ const generateExpressionsComputation = (variables, expressions) => {
|
|
|
169
219
|
depsById
|
|
170
220
|
);
|
|
171
221
|
let generatedCode = "";
|
|
172
|
-
for (const id of
|
|
222
|
+
for (const id of inputVariables) {
|
|
173
223
|
generatedCode += `const ${id} = _variables.get('${id}');
|
|
174
224
|
`;
|
|
175
225
|
}
|
|
@@ -190,10 +240,58 @@ const generateExpressionsComputation = (variables, expressions) => {
|
|
|
190
240
|
generatedCode += `]);`;
|
|
191
241
|
return generatedCode;
|
|
192
242
|
};
|
|
193
|
-
const
|
|
194
|
-
const generatedCode =
|
|
195
|
-
|
|
196
|
-
|
|
243
|
+
const executeComputingExpressions = (expressions, variables) => {
|
|
244
|
+
const generatedCode = generateComputingExpressions(
|
|
245
|
+
expressions,
|
|
246
|
+
new Set(variables.keys())
|
|
247
|
+
);
|
|
248
|
+
const executeFn = new Function("_variables", generatedCode);
|
|
249
|
+
const values = executeFn(variables);
|
|
250
|
+
return values;
|
|
251
|
+
};
|
|
252
|
+
const generateEffectfulExpression = (code, allowedVariables) => {
|
|
253
|
+
const inputVariables = /* @__PURE__ */ new Set();
|
|
254
|
+
const outputVariables = /* @__PURE__ */ new Set();
|
|
255
|
+
validateExpression(code, {
|
|
256
|
+
effectful: true,
|
|
257
|
+
transformIdentifier: (identifier, assignee) => {
|
|
258
|
+
if (allowedVariables.has(identifier)) {
|
|
259
|
+
if (assignee) {
|
|
260
|
+
outputVariables.add(identifier);
|
|
261
|
+
} else {
|
|
262
|
+
inputVariables.add(identifier);
|
|
263
|
+
}
|
|
264
|
+
return identifier;
|
|
265
|
+
}
|
|
266
|
+
throw Error(`Unknown dependency "${identifier}"`);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
let generatedCode = "";
|
|
270
|
+
for (const id of inputVariables) {
|
|
271
|
+
generatedCode += `let ${id} = _variables.get('${id}');
|
|
272
|
+
`;
|
|
273
|
+
}
|
|
274
|
+
for (const id of outputVariables) {
|
|
275
|
+
if (inputVariables.has(id) === false) {
|
|
276
|
+
generatedCode += `let ${id};
|
|
277
|
+
`;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
generatedCode += `${code};
|
|
281
|
+
`;
|
|
282
|
+
generatedCode += `return new Map([
|
|
283
|
+
`;
|
|
284
|
+
for (const id of outputVariables) {
|
|
285
|
+
generatedCode += ` ['${id}', ${id}],
|
|
286
|
+
`;
|
|
287
|
+
}
|
|
288
|
+
generatedCode += `]);`;
|
|
289
|
+
return generatedCode;
|
|
290
|
+
};
|
|
291
|
+
const executeEffectfulExpression = (code, variables) => {
|
|
292
|
+
const generatedCode = generateEffectfulExpression(
|
|
293
|
+
code,
|
|
294
|
+
new Set(variables.keys())
|
|
197
295
|
);
|
|
198
296
|
const executeFn = new Function("_variables", generatedCode);
|
|
199
297
|
const values = executeFn(variables);
|
|
@@ -204,6 +302,13 @@ const encodeDataSourceVariable = (id) => {
|
|
|
204
302
|
const encoded = id.replaceAll("-", "__DASH__");
|
|
205
303
|
return `${dataSourceVariablePrefix}${encoded}`;
|
|
206
304
|
};
|
|
305
|
+
const encodeVariablesMap = (values) => {
|
|
306
|
+
const encodedValues = /* @__PURE__ */ new Map();
|
|
307
|
+
for (const [id, value] of values) {
|
|
308
|
+
encodedValues.set(encodeDataSourceVariable(id), value);
|
|
309
|
+
}
|
|
310
|
+
return encodedValues;
|
|
311
|
+
};
|
|
207
312
|
const decodeDataSourceVariable = (name) => {
|
|
208
313
|
if (name.startsWith(dataSourceVariablePrefix)) {
|
|
209
314
|
const encoded = name.slice(dataSourceVariablePrefix.length);
|
|
@@ -211,3 +316,13 @@ const decodeDataSourceVariable = (name) => {
|
|
|
211
316
|
}
|
|
212
317
|
return;
|
|
213
318
|
};
|
|
319
|
+
const decodeVariablesMap = (values) => {
|
|
320
|
+
const decodedValues = /* @__PURE__ */ new Map();
|
|
321
|
+
for (const [name, value] of values) {
|
|
322
|
+
const id = decodeDataSourceVariable(name);
|
|
323
|
+
if (id !== void 0) {
|
|
324
|
+
decodedValues.set(id, value);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return decodedValues;
|
|
328
|
+
};
|
package/lib/cjs/index.js
CHANGED
|
@@ -22,10 +22,14 @@ __export(src_exports, {
|
|
|
22
22
|
ReactSdkContext: () => import_context.ReactSdkContext,
|
|
23
23
|
componentCategories: () => import_component_meta.componentCategories,
|
|
24
24
|
decodeDataSourceVariable: () => import_expression.decodeDataSourceVariable,
|
|
25
|
+
decodeVariablesMap: () => import_expression.decodeVariablesMap,
|
|
25
26
|
defaultStates: () => import_component_meta.defaultStates,
|
|
26
27
|
encodeDataSourceVariable: () => import_expression.encodeDataSourceVariable,
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
encodeVariablesMap: () => import_expression.encodeVariablesMap,
|
|
29
|
+
executeComputingExpressions: () => import_expression.executeComputingExpressions,
|
|
30
|
+
executeEffectfulExpression: () => import_expression.executeEffectfulExpression,
|
|
31
|
+
generateComputingExpressions: () => import_expression.generateComputingExpressions,
|
|
32
|
+
generateEffectfulExpression: () => import_expression.generateEffectfulExpression,
|
|
29
33
|
getInstanceIdFromComponentProps: () => import_props.getInstanceIdFromComponentProps,
|
|
30
34
|
stateCategories: () => import_component_meta.stateCategories,
|
|
31
35
|
useInstanceProps: () => import_props.useInstanceProps,
|
package/lib/cjs/props.js
CHANGED
|
@@ -44,7 +44,13 @@ const getPropsByInstanceId = (props) => {
|
|
|
44
44
|
return propsByInstanceId;
|
|
45
45
|
};
|
|
46
46
|
const useInstanceProps = (instanceId) => {
|
|
47
|
-
const {
|
|
47
|
+
const {
|
|
48
|
+
propsByInstanceIdStore,
|
|
49
|
+
dataSourceValuesStore,
|
|
50
|
+
executeEffectfulExpression,
|
|
51
|
+
setDataSourceValues,
|
|
52
|
+
renderer
|
|
53
|
+
} = (0, import_react.useContext)(import_context.ReactSdkContext);
|
|
48
54
|
const instancePropsObjectStore = (0, import_react.useMemo)(() => {
|
|
49
55
|
return (0, import_nanostores.computed)(
|
|
50
56
|
[propsByInstanceIdStore, dataSourceValuesStore],
|
|
@@ -66,12 +72,36 @@ const useInstanceProps = (instanceId) => {
|
|
|
66
72
|
}
|
|
67
73
|
continue;
|
|
68
74
|
}
|
|
75
|
+
if (prop.type === "action") {
|
|
76
|
+
instancePropsObject2[prop.name] = () => {
|
|
77
|
+
if (renderer === "canvas") {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
for (const value of prop.value) {
|
|
81
|
+
if (value.type === "execute") {
|
|
82
|
+
const newValues = executeEffectfulExpression(
|
|
83
|
+
value.code,
|
|
84
|
+
dataSourceValues
|
|
85
|
+
);
|
|
86
|
+
setDataSourceValues(newValues);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
69
92
|
instancePropsObject2[prop.name] = prop.value;
|
|
70
93
|
}
|
|
71
94
|
return instancePropsObject2;
|
|
72
95
|
}
|
|
73
96
|
);
|
|
74
|
-
}, [
|
|
97
|
+
}, [
|
|
98
|
+
propsByInstanceIdStore,
|
|
99
|
+
dataSourceValuesStore,
|
|
100
|
+
instanceId,
|
|
101
|
+
renderer,
|
|
102
|
+
executeEffectfulExpression,
|
|
103
|
+
setDataSourceValues
|
|
104
|
+
]);
|
|
75
105
|
const instancePropsObject = (0, import_react2.useStore)(instancePropsObjectStore);
|
|
76
106
|
return instancePropsObject;
|
|
77
107
|
};
|
|
@@ -35,6 +35,7 @@ const createElementsTree = ({
|
|
|
35
35
|
assetsStore,
|
|
36
36
|
pagesStore,
|
|
37
37
|
dataSourceValuesStore,
|
|
38
|
+
executeEffectfulExpression,
|
|
38
39
|
onDataSourceUpdate,
|
|
39
40
|
Component,
|
|
40
41
|
components
|
|
@@ -75,7 +76,9 @@ const createElementsTree = ({
|
|
|
75
76
|
renderer,
|
|
76
77
|
imageBaseUrl,
|
|
77
78
|
assetBaseUrl,
|
|
78
|
-
|
|
79
|
+
executeEffectfulExpression,
|
|
80
|
+
setDataSourceValues: onDataSourceUpdate,
|
|
81
|
+
setBoundDataSourceValue: (instanceId, propName, value) => {
|
|
79
82
|
const propsByInstanceId = propsByInstanceIdStore.get();
|
|
80
83
|
const props = propsByInstanceId.get(instanceId);
|
|
81
84
|
const prop = props?.find((prop2) => prop2.name === propName);
|
|
@@ -83,7 +86,9 @@ const createElementsTree = ({
|
|
|
83
86
|
throw Error(`${propName} is not data source`);
|
|
84
87
|
}
|
|
85
88
|
const dataSourceId = prop.value;
|
|
86
|
-
|
|
89
|
+
const newValues = /* @__PURE__ */ new Map();
|
|
90
|
+
newValues.set(dataSourceId, value);
|
|
91
|
+
onDataSourceUpdate(newValues);
|
|
87
92
|
}
|
|
88
93
|
},
|
|
89
94
|
children: root
|
package/lib/cjs/tree/root.js
CHANGED
|
@@ -28,7 +28,8 @@ var import_webstudio_component = require("./webstudio-component");
|
|
|
28
28
|
var import_props = require("../props");
|
|
29
29
|
const InstanceRoot = ({
|
|
30
30
|
data,
|
|
31
|
-
|
|
31
|
+
executeComputingExpressions,
|
|
32
|
+
executeEffectfulExpression,
|
|
32
33
|
Component,
|
|
33
34
|
components
|
|
34
35
|
}) => {
|
|
@@ -50,7 +51,7 @@ const InstanceRoot = ({
|
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
try {
|
|
53
|
-
const result =
|
|
54
|
+
const result = executeComputingExpressions(dataSourceValues);
|
|
54
55
|
for (const [id, value] of result) {
|
|
55
56
|
dataSourceValues.set(id, value);
|
|
56
57
|
}
|
|
@@ -62,6 +63,16 @@ const InstanceRoot = ({
|
|
|
62
63
|
);
|
|
63
64
|
}
|
|
64
65
|
const dataSourceValuesStore = dataSourceValuesStoreRef.current;
|
|
66
|
+
const onDataSourceUpdate = (0, import_react.useCallback)(
|
|
67
|
+
(newValues) => {
|
|
68
|
+
const dataSourceVariables = new Map(dataSourceVariablesStore.get());
|
|
69
|
+
for (const [dataSourceId, value] of newValues) {
|
|
70
|
+
dataSourceVariables.set(dataSourceId, value);
|
|
71
|
+
}
|
|
72
|
+
dataSourceVariablesStore.set(dataSourceVariables);
|
|
73
|
+
},
|
|
74
|
+
[dataSourceVariablesStore]
|
|
75
|
+
);
|
|
65
76
|
return (0, import_create_elements_tree.createElementsTree)({
|
|
66
77
|
imageBaseUrl: data.params?.imageBaseUrl ?? "/",
|
|
67
78
|
assetBaseUrl: data.params?.assetBaseUrl ?? "/",
|
|
@@ -72,12 +83,9 @@ const InstanceRoot = ({
|
|
|
72
83
|
),
|
|
73
84
|
assetsStore: (0, import_nanostores.atom)(new Map(data.assets.map((asset) => [asset.id, asset]))),
|
|
74
85
|
pagesStore: (0, import_nanostores.atom)(new Map(data.pages.map((page) => [page.id, page]))),
|
|
86
|
+
executeEffectfulExpression,
|
|
75
87
|
dataSourceValuesStore,
|
|
76
|
-
onDataSourceUpdate
|
|
77
|
-
const dataSourceVariables = new Map(dataSourceVariablesStore.get());
|
|
78
|
-
dataSourceVariables.set(dataSourceId, value);
|
|
79
|
-
dataSourceVariablesStore.set(dataSourceVariables);
|
|
80
|
-
},
|
|
88
|
+
onDataSourceUpdate,
|
|
81
89
|
Component: Component ?? import_webstudio_component.WebstudioComponent,
|
|
82
90
|
components
|
|
83
91
|
});
|
package/lib/context.js
CHANGED
|
@@ -7,8 +7,14 @@ const ReactSdkContext = createContext({
|
|
|
7
7
|
assetsStore: atom(/* @__PURE__ */ new Map()),
|
|
8
8
|
pagesStore: atom(/* @__PURE__ */ new Map()),
|
|
9
9
|
dataSourceValuesStore: atom(/* @__PURE__ */ new Map()),
|
|
10
|
-
|
|
11
|
-
throw Error("React SDK
|
|
10
|
+
executeEffectfulExpression: () => {
|
|
11
|
+
throw Error("React SDK executeEffectfulExpression is not implemented");
|
|
12
|
+
},
|
|
13
|
+
setDataSourceValues: () => {
|
|
14
|
+
throw Error("React SDK setBoundDataSourceValue is not implemented");
|
|
15
|
+
},
|
|
16
|
+
setBoundDataSourceValue: () => {
|
|
17
|
+
throw Error("React SDK setBoundDataSourceValue is not implemented");
|
|
12
18
|
}
|
|
13
19
|
});
|
|
14
20
|
export {
|
package/lib/css/normalize.js
CHANGED
package/lib/embed-template.js
CHANGED
|
@@ -6,11 +6,12 @@ const EmbedTemplateText = z.object({
|
|
|
6
6
|
type: z.literal("text"),
|
|
7
7
|
value: z.string()
|
|
8
8
|
});
|
|
9
|
+
const DataSourceVariableRef = z.object({
|
|
10
|
+
type: z.literal("variable"),
|
|
11
|
+
name: z.string()
|
|
12
|
+
});
|
|
9
13
|
const DataSourceRef = z.union([
|
|
10
|
-
|
|
11
|
-
type: z.literal("variable"),
|
|
12
|
-
name: z.string()
|
|
13
|
-
}),
|
|
14
|
+
DataSourceVariableRef,
|
|
14
15
|
z.object({
|
|
15
16
|
type: z.literal("expression"),
|
|
16
17
|
name: z.string(),
|
|
@@ -41,6 +42,16 @@ const EmbedTemplateProp = z.union([
|
|
|
41
42
|
name: z.string(),
|
|
42
43
|
dataSourceRef: z.optional(DataSourceRef),
|
|
43
44
|
value: z.array(z.string())
|
|
45
|
+
}),
|
|
46
|
+
z.object({
|
|
47
|
+
type: z.literal("action"),
|
|
48
|
+
name: z.string(),
|
|
49
|
+
value: z.array(
|
|
50
|
+
z.object({
|
|
51
|
+
type: z.literal("execute"),
|
|
52
|
+
code: z.string()
|
|
53
|
+
})
|
|
54
|
+
)
|
|
44
55
|
})
|
|
45
56
|
]);
|
|
46
57
|
const EmbedTemplateStyleDeclRaw = z.object({
|
|
@@ -71,6 +82,28 @@ const createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceB
|
|
|
71
82
|
if (item.props) {
|
|
72
83
|
for (const prop of item.props) {
|
|
73
84
|
const propId = nanoid();
|
|
85
|
+
if (prop.type === "action") {
|
|
86
|
+
props.push({
|
|
87
|
+
id: propId,
|
|
88
|
+
instanceId,
|
|
89
|
+
type: "action",
|
|
90
|
+
name: prop.name,
|
|
91
|
+
value: prop.value.map((value) => {
|
|
92
|
+
return {
|
|
93
|
+
type: "execute",
|
|
94
|
+
// replace all references with variable names
|
|
95
|
+
code: validateExpression(value.code, {
|
|
96
|
+
effectful: true,
|
|
97
|
+
transformIdentifier: (ref) => {
|
|
98
|
+
const id = dataSourceByRef.get(ref)?.id ?? ref;
|
|
99
|
+
return encodeDataSourceVariable(id);
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
};
|
|
103
|
+
})
|
|
104
|
+
});
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
74
107
|
if (prop.dataSourceRef === void 0) {
|
|
75
108
|
props.push({ id: propId, instanceId, ...prop });
|
|
76
109
|
continue;
|
|
@@ -95,7 +128,13 @@ const createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceB
|
|
|
95
128
|
id,
|
|
96
129
|
scopeInstanceId: instanceId,
|
|
97
130
|
name: dataSourceRef.name,
|
|
98
|
-
|
|
131
|
+
// replace all references with variable names
|
|
132
|
+
code: validateExpression(dataSourceRef.code, {
|
|
133
|
+
transformIdentifier: (ref) => {
|
|
134
|
+
const id2 = dataSourceByRef.get(ref)?.id ?? ref;
|
|
135
|
+
return encodeDataSourceVariable(id2);
|
|
136
|
+
}
|
|
137
|
+
})
|
|
99
138
|
};
|
|
100
139
|
dataSourceByRef.set(dataSourceRef.name, dataSource);
|
|
101
140
|
} else {
|
|
@@ -181,21 +220,11 @@ const generateDataFromEmbedTemplate = (treeTemplate, defaultBreakpointId) => {
|
|
|
181
220
|
styles,
|
|
182
221
|
defaultBreakpointId
|
|
183
222
|
);
|
|
184
|
-
const dataSources = [];
|
|
185
|
-
for (const dataSource of dataSourceByRef.values()) {
|
|
186
|
-
if (dataSource.type === "expression") {
|
|
187
|
-
dataSource.code = validateExpression(dataSource.code, (ref) => {
|
|
188
|
-
const id = dataSourceByRef.get(ref)?.id ?? ref;
|
|
189
|
-
return encodeDataSourceVariable(id);
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
dataSources.push(dataSource);
|
|
193
|
-
}
|
|
194
223
|
return {
|
|
195
224
|
children,
|
|
196
225
|
instances,
|
|
197
226
|
props,
|
|
198
|
-
dataSources,
|
|
227
|
+
dataSources: Array.from(dataSourceByRef.values()),
|
|
199
228
|
styleSourceSelections,
|
|
200
229
|
styleSources,
|
|
201
230
|
styles
|