@webstudio-is/react-sdk 0.79.0 → 0.81.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.
@@ -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
- setDataSourceValue: () => {
34
- throw Error("React SDK setDataSourceValue is not implemented");
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
  });
@@ -141,7 +141,7 @@ const body = [
141
141
  property: "fontFamily",
142
142
  value: {
143
143
  type: "keyword",
144
- value: "Arial, sans-serif"
144
+ value: "Arial, Roboto, sans-serif"
145
145
  }
146
146
  },
147
147
  {
@@ -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
- import_zod.z.object({
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
- code: dataSourceRef.code
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
@@ -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
- executeExpressions: () => executeExpressions,
34
- generateExpressionsComputation: () => generateExpressionsComputation,
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
- const generateCode = (node, failOnForbidden, transformIdentifier) => {
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(element, failOnForbidden, transformIdentifier)
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, transformIdentifier = (id) => id) => {
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 generateExpressionsComputation = (variables, expressions) => {
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, (identifier) => {
156
- if (variables.has(identifier)) {
157
- return identifier;
158
- }
159
- if (expressions.has(identifier)) {
160
- deps.add(identifier);
161
- return identifier;
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 variables) {
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 executeExpressions = (variables, expressions) => {
194
- const generatedCode = generateExpressionsComputation(
195
- new Set(variables.keys()),
196
- expressions
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
- executeExpressions: () => import_expression.executeExpressions,
28
- generateExpressionsComputation: () => import_expression.generateExpressionsComputation,
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 { propsByInstanceIdStore, dataSourceValuesStore } = (0, import_react.useContext)(import_context.ReactSdkContext);
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
- }, [propsByInstanceIdStore, dataSourceValuesStore, instanceId]);
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
- setDataSourceValue: (instanceId, propName, value) => {
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
- onDataSourceUpdate(dataSourceId, value);
89
+ const newValues = /* @__PURE__ */ new Map();
90
+ newValues.set(dataSourceId, value);
91
+ onDataSourceUpdate(newValues);
87
92
  }
88
93
  },
89
94
  children: root
@@ -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
- computeExpressions,
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 = computeExpressions(dataSourceValues);
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: (dataSourceId, value) => {
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
- setDataSourceValue: () => {
11
- throw Error("React SDK setDataSourceValue is not implemented");
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 {
@@ -72,7 +72,7 @@ const body = [
72
72
  property: "fontFamily",
73
73
  value: {
74
74
  type: "keyword",
75
- value: "Arial, sans-serif"
75
+ value: "Arial, Roboto, sans-serif"
76
76
  }
77
77
  },
78
78
  {
@@ -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
- z.object({
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
- code: dataSourceRef.code
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