@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/expression.js CHANGED
@@ -1,18 +1,22 @@
1
1
  import jsep from "jsep";
2
- const generateCode = (node, failOnForbidden, transformIdentifier) => {
2
+ import jsepAssignment from "@jsep-plugin/assignment";
3
+ jsep.plugins.register(jsepAssignment);
4
+ const generateCode = (node, failOnForbidden, effectful, transformIdentifier) => {
3
5
  if (node.type === "Identifier") {
4
- return transformIdentifier(node.name);
6
+ return transformIdentifier(node.name, false);
5
7
  }
6
8
  if (node.type === "MemberExpression") {
7
9
  if (failOnForbidden) {
8
10
  const object2 = generateCode(
9
11
  node.object,
10
12
  false,
13
+ effectful,
11
14
  transformIdentifier
12
15
  );
13
16
  const property2 = generateCode(
14
17
  node.property,
15
18
  false,
19
+ effectful,
16
20
  transformIdentifier
17
21
  );
18
22
  throw Error(`Cannot access "${property2}" of "${object2}"`);
@@ -20,11 +24,13 @@ const generateCode = (node, failOnForbidden, transformIdentifier) => {
20
24
  const object = generateCode(
21
25
  node.object,
22
26
  failOnForbidden,
27
+ effectful,
23
28
  transformIdentifier
24
29
  );
25
30
  const property = generateCode(
26
31
  node.property,
27
32
  failOnForbidden,
33
+ effectful,
28
34
  transformIdentifier
29
35
  );
30
36
  return `${object}.${property}`;
@@ -36,6 +42,7 @@ const generateCode = (node, failOnForbidden, transformIdentifier) => {
36
42
  const arg = generateCode(
37
43
  node.argument,
38
44
  failOnForbidden,
45
+ effectful,
39
46
  transformIdentifier
40
47
  );
41
48
  return `${node.operator}${arg}`;
@@ -44,18 +51,25 @@ const generateCode = (node, failOnForbidden, transformIdentifier) => {
44
51
  const left = generateCode(
45
52
  node.left,
46
53
  failOnForbidden,
54
+ effectful,
47
55
  transformIdentifier
48
56
  );
49
57
  const right = generateCode(
50
58
  node.right,
51
59
  failOnForbidden,
60
+ effectful,
52
61
  transformIdentifier
53
62
  );
54
63
  return `${left} ${node.operator} ${right}`;
55
64
  }
56
65
  if (node.type === "ArrayExpression") {
57
66
  const elements = node.elements.map(
58
- (element) => generateCode(element, failOnForbidden, transformIdentifier)
67
+ (element) => generateCode(
68
+ element,
69
+ failOnForbidden,
70
+ effectful,
71
+ transformIdentifier
72
+ )
59
73
  );
60
74
  return `[${elements.join(", ")}]`;
61
75
  }
@@ -64,6 +78,7 @@ const generateCode = (node, failOnForbidden, transformIdentifier) => {
64
78
  const callee2 = generateCode(
65
79
  node.callee,
66
80
  false,
81
+ effectful,
67
82
  transformIdentifier
68
83
  );
69
84
  throw Error(`Cannot call "${callee2}"`);
@@ -71,10 +86,11 @@ const generateCode = (node, failOnForbidden, transformIdentifier) => {
71
86
  const callee = generateCode(
72
87
  node.callee,
73
88
  failOnForbidden,
89
+ effectful,
74
90
  transformIdentifier
75
91
  );
76
92
  const args = node.arguments.map(
77
- (arg) => generateCode(arg, failOnForbidden, transformIdentifier)
93
+ (arg) => generateCode(arg, failOnForbidden, effectful, transformIdentifier)
78
94
  );
79
95
  return `${callee}(${args.join(", ")})`;
80
96
  }
@@ -90,12 +106,38 @@ const generateCode = (node, failOnForbidden, transformIdentifier) => {
90
106
  if (node.type === "Compound") {
91
107
  throw Error("Cannot use multiple expressions");
92
108
  }
109
+ if (node.type === "AssignmentExpression") {
110
+ if (node.operator !== "=") {
111
+ throw Error(`Only "=" assignment operator is supported`);
112
+ }
113
+ if (effectful === false) {
114
+ throw Error(`Cannot use assignment in this expression`);
115
+ }
116
+ const left = generateCode(
117
+ node.left,
118
+ failOnForbidden,
119
+ effectful,
120
+ // override and mark all identifiers inside of left expression as assignee
121
+ (id) => transformIdentifier(id, true)
122
+ );
123
+ const right = generateCode(
124
+ node.right,
125
+ failOnForbidden,
126
+ effectful,
127
+ transformIdentifier
128
+ );
129
+ return `${left} ${node.operator} ${right}`;
130
+ }
131
+ if (node.type === "UpdateExpression") {
132
+ throw Error(`"${node.operator}" operator is not supported`);
133
+ }
93
134
  node;
94
135
  return "";
95
136
  };
96
- const validateExpression = (code, transformIdentifier = (id) => id) => {
137
+ const validateExpression = (code, options) => {
138
+ const { effectful = false, transformIdentifier = (id) => id } = options ?? {};
97
139
  const expression = jsep(code);
98
- return generateCode(expression, true, transformIdentifier);
140
+ return generateCode(expression, true, effectful, transformIdentifier);
99
141
  };
100
142
  const sortTopologically = (list, depsById, explored = /* @__PURE__ */ new Set(), sorted = []) => {
101
143
  for (const id of list) {
@@ -111,19 +153,23 @@ const sortTopologically = (list, depsById, explored = /* @__PURE__ */ new Set(),
111
153
  }
112
154
  return sorted;
113
155
  };
114
- const generateExpressionsComputation = (variables, expressions) => {
156
+ const generateComputingExpressions = (expressions, allowedVariables) => {
115
157
  const depsById = /* @__PURE__ */ new Map();
158
+ const inputVariables = /* @__PURE__ */ new Set();
116
159
  for (const [id, code] of expressions) {
117
160
  const deps = /* @__PURE__ */ new Set();
118
- validateExpression(code, (identifier) => {
119
- if (variables.has(identifier)) {
120
- return identifier;
121
- }
122
- if (expressions.has(identifier)) {
123
- deps.add(identifier);
124
- return identifier;
161
+ validateExpression(code, {
162
+ transformIdentifier: (identifier) => {
163
+ if (allowedVariables.has(identifier)) {
164
+ inputVariables.add(identifier);
165
+ return identifier;
166
+ }
167
+ if (expressions.has(identifier)) {
168
+ deps.add(identifier);
169
+ return identifier;
170
+ }
171
+ throw Error(`Unknown dependency "${identifier}"`);
125
172
  }
126
- throw Error(`Unknown dependency "${identifier}"`);
127
173
  });
128
174
  depsById.set(id, deps);
129
175
  }
@@ -132,7 +178,7 @@ const generateExpressionsComputation = (variables, expressions) => {
132
178
  depsById
133
179
  );
134
180
  let generatedCode = "";
135
- for (const id of variables) {
181
+ for (const id of inputVariables) {
136
182
  generatedCode += `const ${id} = _variables.get('${id}');
137
183
  `;
138
184
  }
@@ -153,10 +199,58 @@ const generateExpressionsComputation = (variables, expressions) => {
153
199
  generatedCode += `]);`;
154
200
  return generatedCode;
155
201
  };
156
- const executeExpressions = (variables, expressions) => {
157
- const generatedCode = generateExpressionsComputation(
158
- new Set(variables.keys()),
159
- expressions
202
+ const executeComputingExpressions = (expressions, variables) => {
203
+ const generatedCode = generateComputingExpressions(
204
+ expressions,
205
+ new Set(variables.keys())
206
+ );
207
+ const executeFn = new Function("_variables", generatedCode);
208
+ const values = executeFn(variables);
209
+ return values;
210
+ };
211
+ const generateEffectfulExpression = (code, allowedVariables) => {
212
+ const inputVariables = /* @__PURE__ */ new Set();
213
+ const outputVariables = /* @__PURE__ */ new Set();
214
+ validateExpression(code, {
215
+ effectful: true,
216
+ transformIdentifier: (identifier, assignee) => {
217
+ if (allowedVariables.has(identifier)) {
218
+ if (assignee) {
219
+ outputVariables.add(identifier);
220
+ } else {
221
+ inputVariables.add(identifier);
222
+ }
223
+ return identifier;
224
+ }
225
+ throw Error(`Unknown dependency "${identifier}"`);
226
+ }
227
+ });
228
+ let generatedCode = "";
229
+ for (const id of inputVariables) {
230
+ generatedCode += `let ${id} = _variables.get('${id}');
231
+ `;
232
+ }
233
+ for (const id of outputVariables) {
234
+ if (inputVariables.has(id) === false) {
235
+ generatedCode += `let ${id};
236
+ `;
237
+ }
238
+ }
239
+ generatedCode += `${code};
240
+ `;
241
+ generatedCode += `return new Map([
242
+ `;
243
+ for (const id of outputVariables) {
244
+ generatedCode += ` ['${id}', ${id}],
245
+ `;
246
+ }
247
+ generatedCode += `]);`;
248
+ return generatedCode;
249
+ };
250
+ const executeEffectfulExpression = (code, variables) => {
251
+ const generatedCode = generateEffectfulExpression(
252
+ code,
253
+ new Set(variables.keys())
160
254
  );
161
255
  const executeFn = new Function("_variables", generatedCode);
162
256
  const values = executeFn(variables);
@@ -167,6 +261,13 @@ const encodeDataSourceVariable = (id) => {
167
261
  const encoded = id.replaceAll("-", "__DASH__");
168
262
  return `${dataSourceVariablePrefix}${encoded}`;
169
263
  };
264
+ const encodeVariablesMap = (values) => {
265
+ const encodedValues = /* @__PURE__ */ new Map();
266
+ for (const [id, value] of values) {
267
+ encodedValues.set(encodeDataSourceVariable(id), value);
268
+ }
269
+ return encodedValues;
270
+ };
170
271
  const decodeDataSourceVariable = (name) => {
171
272
  if (name.startsWith(dataSourceVariablePrefix)) {
172
273
  const encoded = name.slice(dataSourceVariablePrefix.length);
@@ -174,10 +275,24 @@ const decodeDataSourceVariable = (name) => {
174
275
  }
175
276
  return;
176
277
  };
278
+ const decodeVariablesMap = (values) => {
279
+ const decodedValues = /* @__PURE__ */ new Map();
280
+ for (const [name, value] of values) {
281
+ const id = decodeDataSourceVariable(name);
282
+ if (id !== void 0) {
283
+ decodedValues.set(id, value);
284
+ }
285
+ }
286
+ return decodedValues;
287
+ };
177
288
  export {
178
289
  decodeDataSourceVariable,
290
+ decodeVariablesMap,
179
291
  encodeDataSourceVariable,
180
- executeExpressions,
181
- generateExpressionsComputation,
292
+ encodeVariablesMap,
293
+ executeComputingExpressions,
294
+ executeEffectfulExpression,
295
+ generateComputingExpressions,
296
+ generateEffectfulExpression,
182
297
  validateExpression
183
298
  };
package/lib/index.js CHANGED
@@ -18,19 +18,27 @@ import {
18
18
  import { ReactSdkContext } from "./context";
19
19
  import {
20
20
  validateExpression,
21
- generateExpressionsComputation,
22
- executeExpressions,
21
+ generateComputingExpressions,
22
+ executeComputingExpressions,
23
+ generateEffectfulExpression,
24
+ executeEffectfulExpression,
23
25
  encodeDataSourceVariable,
24
- decodeDataSourceVariable
26
+ encodeVariablesMap,
27
+ decodeDataSourceVariable,
28
+ decodeVariablesMap
25
29
  } from "./expression";
26
30
  export {
27
31
  ReactSdkContext,
28
32
  componentCategories,
29
33
  decodeDataSourceVariable,
34
+ decodeVariablesMap,
30
35
  defaultStates,
31
36
  encodeDataSourceVariable,
32
- executeExpressions,
33
- generateExpressionsComputation,
37
+ encodeVariablesMap,
38
+ executeComputingExpressions,
39
+ executeEffectfulExpression,
40
+ generateComputingExpressions,
41
+ generateEffectfulExpression,
34
42
  getInstanceIdFromComponentProps,
35
43
  stateCategories,
36
44
  useInstanceProps,
package/lib/props.js CHANGED
@@ -16,7 +16,13 @@ const getPropsByInstanceId = (props) => {
16
16
  return propsByInstanceId;
17
17
  };
18
18
  const useInstanceProps = (instanceId) => {
19
- const { propsByInstanceIdStore, dataSourceValuesStore } = useContext(ReactSdkContext);
19
+ const {
20
+ propsByInstanceIdStore,
21
+ dataSourceValuesStore,
22
+ executeEffectfulExpression,
23
+ setDataSourceValues,
24
+ renderer
25
+ } = useContext(ReactSdkContext);
20
26
  const instancePropsObjectStore = useMemo(() => {
21
27
  return computed(
22
28
  [propsByInstanceIdStore, dataSourceValuesStore],
@@ -38,12 +44,36 @@ const useInstanceProps = (instanceId) => {
38
44
  }
39
45
  continue;
40
46
  }
47
+ if (prop.type === "action") {
48
+ instancePropsObject2[prop.name] = () => {
49
+ if (renderer === "canvas") {
50
+ return;
51
+ }
52
+ for (const value of prop.value) {
53
+ if (value.type === "execute") {
54
+ const newValues = executeEffectfulExpression(
55
+ value.code,
56
+ dataSourceValues
57
+ );
58
+ setDataSourceValues(newValues);
59
+ }
60
+ }
61
+ };
62
+ continue;
63
+ }
41
64
  instancePropsObject2[prop.name] = prop.value;
42
65
  }
43
66
  return instancePropsObject2;
44
67
  }
45
68
  );
46
- }, [propsByInstanceIdStore, dataSourceValuesStore, instanceId]);
69
+ }, [
70
+ propsByInstanceIdStore,
71
+ dataSourceValuesStore,
72
+ instanceId,
73
+ renderer,
74
+ executeEffectfulExpression,
75
+ setDataSourceValues
76
+ ]);
47
77
  const instancePropsObject = useStore(instancePropsObjectStore);
48
78
  return instancePropsObject;
49
79
  };
@@ -1,7 +1,9 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Fragment } from "react";
3
3
  import { Scripts, ScrollRestoration } from "@remix-run/react";
4
- import { ReactSdkContext } from "../context";
4
+ import {
5
+ ReactSdkContext
6
+ } from "../context";
5
7
  const createElementsTree = ({
6
8
  renderer,
7
9
  imageBaseUrl,
@@ -12,6 +14,7 @@ const createElementsTree = ({
12
14
  assetsStore,
13
15
  pagesStore,
14
16
  dataSourceValuesStore,
17
+ executeEffectfulExpression,
15
18
  onDataSourceUpdate,
16
19
  Component,
17
20
  components
@@ -52,7 +55,9 @@ const createElementsTree = ({
52
55
  renderer,
53
56
  imageBaseUrl,
54
57
  assetBaseUrl,
55
- setDataSourceValue: (instanceId, propName, value) => {
58
+ executeEffectfulExpression,
59
+ setDataSourceValues: onDataSourceUpdate,
60
+ setBoundDataSourceValue: (instanceId, propName, value) => {
56
61
  const propsByInstanceId = propsByInstanceIdStore.get();
57
62
  const props = propsByInstanceId.get(instanceId);
58
63
  const prop = props?.find((prop2) => prop2.name === propName);
@@ -60,7 +65,9 @@ const createElementsTree = ({
60
65
  throw Error(`${propName} is not data source`);
61
66
  }
62
67
  const dataSourceId = prop.value;
63
- onDataSourceUpdate(dataSourceId, value);
68
+ const newValues = /* @__PURE__ */ new Map();
69
+ newValues.set(dataSourceId, value);
70
+ onDataSourceUpdate(newValues);
64
71
  }
65
72
  },
66
73
  children: root
package/lib/tree/root.js CHANGED
@@ -1,4 +1,4 @@
1
- import { useRef } from "react";
1
+ import { useRef, useCallback } from "react";
2
2
  import {
3
3
  atom,
4
4
  computed
@@ -8,7 +8,8 @@ import { WebstudioComponent } from "./webstudio-component";
8
8
  import { getPropsByInstanceId } from "../props";
9
9
  const InstanceRoot = ({
10
10
  data,
11
- computeExpressions,
11
+ executeComputingExpressions,
12
+ executeEffectfulExpression,
12
13
  Component,
13
14
  components
14
15
  }) => {
@@ -30,7 +31,7 @@ const InstanceRoot = ({
30
31
  }
31
32
  }
32
33
  try {
33
- const result = computeExpressions(dataSourceValues);
34
+ const result = executeComputingExpressions(dataSourceValues);
34
35
  for (const [id, value] of result) {
35
36
  dataSourceValues.set(id, value);
36
37
  }
@@ -42,6 +43,16 @@ const InstanceRoot = ({
42
43
  );
43
44
  }
44
45
  const dataSourceValuesStore = dataSourceValuesStoreRef.current;
46
+ const onDataSourceUpdate = useCallback(
47
+ (newValues) => {
48
+ const dataSourceVariables = new Map(dataSourceVariablesStore.get());
49
+ for (const [dataSourceId, value] of newValues) {
50
+ dataSourceVariables.set(dataSourceId, value);
51
+ }
52
+ dataSourceVariablesStore.set(dataSourceVariables);
53
+ },
54
+ [dataSourceVariablesStore]
55
+ );
45
56
  return createElementsTree({
46
57
  imageBaseUrl: data.params?.imageBaseUrl ?? "/",
47
58
  assetBaseUrl: data.params?.assetBaseUrl ?? "/",
@@ -52,12 +63,9 @@ const InstanceRoot = ({
52
63
  ),
53
64
  assetsStore: atom(new Map(data.assets.map((asset) => [asset.id, asset]))),
54
65
  pagesStore: atom(new Map(data.pages.map((page) => [page.id, page]))),
66
+ executeEffectfulExpression,
55
67
  dataSourceValuesStore,
56
- onDataSourceUpdate: (dataSourceId, value) => {
57
- const dataSourceVariables = new Map(dataSourceVariablesStore.get());
58
- dataSourceVariables.set(dataSourceId, value);
59
- dataSourceVariablesStore.set(dataSourceVariables);
60
- },
68
+ onDataSourceUpdate,
61
69
  Component: Component ?? WebstudioComponent,
62
70
  components
63
71
  });
@@ -366,6 +366,24 @@ declare const WsComponentPropsMeta: z.ZodObject<{
366
366
  defaultValue?: string | undefined;
367
367
  label?: string | undefined;
368
368
  description?: string | undefined;
369
+ }>, z.ZodObject<{
370
+ control: z.ZodLiteral<"action">;
371
+ type: z.ZodLiteral<"action">;
372
+ label: z.ZodOptional<z.ZodString>;
373
+ description: z.ZodOptional<z.ZodString>;
374
+ required: z.ZodBoolean;
375
+ }, "strip", z.ZodTypeAny, {
376
+ type: "action";
377
+ required: boolean;
378
+ control: "action";
379
+ label?: string | undefined;
380
+ description?: string | undefined;
381
+ }, {
382
+ type: "action";
383
+ required: boolean;
384
+ control: "action";
385
+ label?: string | undefined;
386
+ description?: string | undefined;
369
387
  }>]>>;
370
388
  initialProps: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
371
389
  }, "strip", z.ZodTypeAny, {
@@ -490,6 +508,12 @@ declare const WsComponentPropsMeta: z.ZodObject<{
490
508
  defaultValue?: string | undefined;
491
509
  label?: string | undefined;
492
510
  description?: string | undefined;
511
+ } | {
512
+ type: "action";
513
+ required: boolean;
514
+ control: "action";
515
+ label?: string | undefined;
516
+ description?: string | undefined;
493
517
  }>;
494
518
  initialProps?: string[] | undefined;
495
519
  }, {
@@ -614,6 +638,12 @@ declare const WsComponentPropsMeta: z.ZodObject<{
614
638
  defaultValue?: string | undefined;
615
639
  label?: string | undefined;
616
640
  description?: string | undefined;
641
+ } | {
642
+ type: "action";
643
+ required: boolean;
644
+ control: "action";
645
+ label?: string | undefined;
646
+ description?: string | undefined;
617
647
  }>;
618
648
  initialProps?: string[] | undefined;
619
649
  }>;
@@ -29,10 +29,13 @@ export type Params = {
29
29
  */
30
30
  assetBaseUrl: string;
31
31
  };
32
+ export type DataSourceValues = Map<DataSource["id"], unknown>;
32
33
  export declare const ReactSdkContext: import("react").Context<Params & {
33
34
  propsByInstanceIdStore: ReadableAtom<PropsByInstanceId>;
34
35
  assetsStore: ReadableAtom<Assets>;
35
36
  pagesStore: ReadableAtom<Pages>;
36
- dataSourceValuesStore: ReadableAtom<Map<DataSource["id"], unknown>>;
37
- setDataSourceValue: (instanceId: Instance["id"], prop: Prop["name"], value: unknown) => void;
37
+ dataSourceValuesStore: ReadableAtom<DataSourceValues>;
38
+ executeEffectfulExpression: (expression: string, values: DataSourceValues) => DataSourceValues;
39
+ setDataSourceValues: (newValues: DataSourceValues) => void;
40
+ setBoundDataSourceValue: (instanceId: Instance["id"], prop: Prop["name"], value: unknown) => void;
38
41
  }>;
@@ -213,6 +213,33 @@ declare const EmbedTemplateProp: z.ZodUnion<[z.ZodObject<{
213
213
  code: string;
214
214
  type: "expression";
215
215
  } | undefined;
216
+ }>, z.ZodObject<{
217
+ type: z.ZodLiteral<"action">;
218
+ name: z.ZodString;
219
+ value: z.ZodArray<z.ZodObject<{
220
+ type: z.ZodLiteral<"execute">;
221
+ code: z.ZodString;
222
+ }, "strip", z.ZodTypeAny, {
223
+ code: string;
224
+ type: "execute";
225
+ }, {
226
+ code: string;
227
+ type: "execute";
228
+ }>, "many">;
229
+ }, "strip", z.ZodTypeAny, {
230
+ name: string;
231
+ type: "action";
232
+ value: {
233
+ code: string;
234
+ type: "execute";
235
+ }[];
236
+ }, {
237
+ name: string;
238
+ type: "action";
239
+ value: {
240
+ code: string;
241
+ type: "execute";
242
+ }[];
216
243
  }>]>;
217
244
  type EmbedTemplateProp = z.infer<typeof EmbedTemplateProp>;
218
245
  declare const EmbedTemplateStyleDeclRaw: z.ZodObject<{
@@ -2357,6 +2384,16 @@ export declare const generateDataFromEmbedTemplate: (treeTemplate: ({
2357
2384
  id: string;
2358
2385
  instanceId: string;
2359
2386
  required?: boolean | undefined;
2387
+ } | {
2388
+ name: string;
2389
+ type: "action";
2390
+ value: {
2391
+ code: string;
2392
+ type: "execute";
2393
+ }[];
2394
+ id: string;
2395
+ instanceId: string;
2396
+ required?: boolean | undefined;
2360
2397
  })[];
2361
2398
  dataSources: ({
2362
2399
  name: string;
@@ -2611,4 +2648,5 @@ export declare const generateDataFromEmbedTemplate: (treeTemplate: ({
2611
2648
  property: "filter" | "float" | "fontFamily" | "width" | "height" | "clip" | "top" | "right" | `--${string}` | "accentColor" | "alignContent" | "alignItems" | "alignSelf" | "alignTracks" | "animationComposition" | "animationDelay" | "animationDirection" | "animationDuration" | "animationFillMode" | "animationIterationCount" | "animationName" | "animationPlayState" | "animationTimingFunction" | "animationTimeline" | "appearance" | "aspectRatio" | "backdropFilter" | "backfaceVisibility" | "backgroundAttachment" | "backgroundBlendMode" | "backgroundClip" | "backgroundColor" | "backgroundImage" | "backgroundOrigin" | "backgroundPosition" | "backgroundPositionX" | "backgroundPositionY" | "backgroundRepeat" | "backgroundSize" | "blockOverflow" | "blockSize" | "borderBlockColor" | "borderBlockStyle" | "borderBlockWidth" | "borderBlockEndColor" | "borderBlockEndStyle" | "borderBlockEndWidth" | "borderBlockStartColor" | "borderBlockStartStyle" | "borderBlockStartWidth" | "borderBottomColor" | "borderBottomLeftRadius" | "borderBottomRightRadius" | "borderBottomStyle" | "borderBottomWidth" | "borderCollapse" | "borderEndEndRadius" | "borderEndStartRadius" | "borderImageOutset" | "borderImageRepeat" | "borderImageSlice" | "borderImageSource" | "borderImageWidth" | "borderInlineColor" | "borderInlineStyle" | "borderInlineWidth" | "borderInlineEndColor" | "borderInlineEndStyle" | "borderInlineEndWidth" | "borderInlineStartColor" | "borderInlineStartStyle" | "borderInlineStartWidth" | "borderLeftColor" | "borderLeftStyle" | "borderLeftWidth" | "borderRightColor" | "borderRightStyle" | "borderRightWidth" | "borderSpacing" | "borderStartEndRadius" | "borderStartStartRadius" | "borderTopColor" | "borderTopLeftRadius" | "borderTopRightRadius" | "borderTopStyle" | "borderTopWidth" | "bottom" | "boxDecorationBreak" | "boxShadow" | "boxSizing" | "breakAfter" | "breakBefore" | "breakInside" | "captionSide" | "caretColor" | "caretShape" | "clear" | "clipPath" | "color" | "printColorAdjust" | "colorScheme" | "columnCount" | "columnFill" | "columnGap" | "columnRuleColor" | "columnRuleStyle" | "columnRuleWidth" | "columnSpan" | "columnWidth" | "contain" | "containIntrinsicBlockSize" | "containIntrinsicHeight" | "containIntrinsicInlineSize" | "containIntrinsicWidth" | "content" | "contentVisibility" | "counterIncrement" | "counterReset" | "counterSet" | "cursor" | "direction" | "display" | "emptyCells" | "flexBasis" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "fontFeatureSettings" | "fontKerning" | "fontLanguageOverride" | "fontOpticalSizing" | "fontVariationSettings" | "fontSize" | "fontSizeAdjust" | "fontStretch" | "fontStyle" | "fontSynthesis" | "fontVariant" | "fontVariantAlternates" | "fontVariantCaps" | "fontVariantEastAsian" | "fontVariantLigatures" | "fontVariantNumeric" | "fontVariantPosition" | "fontWeight" | "forcedColorAdjust" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridColumnEnd" | "gridColumnStart" | "gridRowEnd" | "gridRowStart" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "hangingPunctuation" | "hyphenateCharacter" | "hyphens" | "imageOrientation" | "imageRendering" | "imageResolution" | "initialLetter" | "initialLetterAlign" | "inlineSize" | "inputSecurity" | "insetBlockEnd" | "insetBlockStart" | "insetInlineEnd" | "insetInlineStart" | "isolation" | "justifyContent" | "justifyItems" | "justifySelf" | "justifyTracks" | "left" | "letterSpacing" | "lineBreak" | "lineClamp" | "lineHeight" | "lineHeightStep" | "listStyleImage" | "listStylePosition" | "listStyleType" | "marginBlockEnd" | "marginBlockStart" | "marginBottom" | "marginInlineEnd" | "marginInlineStart" | "marginLeft" | "marginRight" | "marginTop" | "marginTrim" | "maskBorderMode" | "maskBorderOutset" | "maskBorderRepeat" | "maskBorderSlice" | "maskBorderSource" | "maskBorderWidth" | "maskClip" | "maskComposite" | "maskImage" | "maskMode" | "maskOrigin" | "maskPosition" | "maskRepeat" | "maskSize" | "maskType" | "masonryAutoFlow" | "mathDepth" | "mathShift" | "mathStyle" | "maxBlockSize" | "maxHeight" | "maxInlineSize" | "maxLines" | "maxWidth" | "minBlockSize" | "minHeight" | "minInlineSize" | "minWidth" | "mixBlendMode" | "objectFit" | "objectPosition" | "offsetAnchor" | "offsetDistance" | "offsetPath" | "offsetPosition" | "offsetRotate" | "opacity" | "order" | "orphans" | "outlineColor" | "outlineOffset" | "outlineStyle" | "outlineWidth" | "overflow" | "overflowAnchor" | "overflowBlock" | "overflowClipMargin" | "overflowInline" | "overflowWrap" | "overflowX" | "overflowY" | "overscrollBehavior" | "overscrollBehaviorBlock" | "overscrollBehaviorInline" | "overscrollBehaviorX" | "overscrollBehaviorY" | "paddingBlockEnd" | "paddingBlockStart" | "paddingBottom" | "paddingInlineEnd" | "paddingInlineStart" | "paddingLeft" | "paddingRight" | "paddingTop" | "pageBreakAfter" | "pageBreakBefore" | "pageBreakInside" | "paintOrder" | "perspective" | "perspectiveOrigin" | "pointerEvents" | "position" | "quotes" | "resize" | "rotate" | "rowGap" | "rubyAlign" | "rubyMerge" | "rubyPosition" | "scale" | "scrollbarColor" | "scrollbarGutter" | "scrollbarWidth" | "scrollBehavior" | "scrollMarginBlockStart" | "scrollMarginBlockEnd" | "scrollMarginBottom" | "scrollMarginInlineStart" | "scrollMarginInlineEnd" | "scrollMarginLeft" | "scrollMarginRight" | "scrollMarginTop" | "scrollPaddingBlockStart" | "scrollPaddingBlockEnd" | "scrollPaddingBottom" | "scrollPaddingInlineStart" | "scrollPaddingInlineEnd" | "scrollPaddingLeft" | "scrollPaddingRight" | "scrollPaddingTop" | "scrollSnapAlign" | "scrollSnapStop" | "scrollSnapType" | "scrollTimelineAxis" | "scrollTimelineName" | "shapeImageThreshold" | "shapeMargin" | "shapeOutside" | "tabSize" | "tableLayout" | "textAlign" | "textAlignLast" | "textCombineUpright" | "textDecorationColor" | "textDecorationLine" | "textDecorationSkip" | "textDecorationSkipInk" | "textDecorationStyle" | "textDecorationThickness" | "textEmphasisColor" | "textEmphasisPosition" | "textEmphasisStyle" | "textIndent" | "textJustify" | "textOrientation" | "textOverflow" | "textRendering" | "textShadow" | "textSizeAdjust" | "textTransform" | "textUnderlineOffset" | "textUnderlinePosition" | "touchAction" | "transform" | "transformBox" | "transformOrigin" | "transformStyle" | "transitionDelay" | "transitionDuration" | "transitionProperty" | "transitionTimingFunction" | "translate" | "unicodeBidi" | "userSelect" | "verticalAlign" | "visibility" | "whiteSpace" | "widows" | "willChange" | "wordBreak" | "wordSpacing" | "wordWrap" | "writingMode" | "zIndex";
2612
2649
  }[];
2613
2650
  };
2651
+ export type EmbedTemplateData = ReturnType<typeof generateDataFromEmbedTemplate>;
2614
2652
  export {};
@@ -1,11 +1,19 @@
1
- type TransformIdentifier = (id: string) => string;
2
- export declare const validateExpression: (code: string, transformIdentifier?: TransformIdentifier) => string;
1
+ type TransformIdentifier = (id: string, assignee: boolean) => string;
2
+ export declare const validateExpression: (code: string, options?: {
3
+ effectful?: boolean;
4
+ transformIdentifier?: TransformIdentifier;
5
+ }) => string;
3
6
  /**
4
7
  * Generates a function body expecting map as _variables argument
5
8
  * and outputing map of results
6
9
  */
7
- export declare const generateExpressionsComputation: (variables: Set<string>, expressions: Map<string, string>) => string;
8
- export declare const executeExpressions: (variables: Map<string, unknown>, expressions: Map<string, string>) => Map<string, unknown>;
10
+ export declare const generateComputingExpressions: (expressions: Map<string, string>, allowedVariables: Set<string>) => string;
11
+ export declare const executeComputingExpressions: (expressions: Map<string, string>, variables: Map<string, unknown>) => Map<string, unknown>;
12
+ export declare const generateEffectfulExpression: (code: string, allowedVariables: Set<string>) => string;
13
+ export declare const executeEffectfulExpression: (code: string, variables: Map<string, unknown>) => Map<string, unknown>;
14
+ type Values = Map<string, unknown>;
9
15
  export declare const encodeDataSourceVariable: (id: string) => string;
16
+ export declare const encodeVariablesMap: (values: Values) => Values;
10
17
  export declare const decodeDataSourceVariable: (name: string) => string | undefined;
18
+ export declare const decodeVariablesMap: (values: Values) => Values;
11
19
  export {};
@@ -7,4 +7,4 @@ export { type WsComponentPropsMeta, type WsComponentMeta, type ComponentState, t
7
7
  export * from "./embed-template";
8
8
  export { useInstanceProps, usePropUrl, usePropAsset, getInstanceIdFromComponentProps, } from "./props";
9
9
  export { type Params, ReactSdkContext } from "./context";
10
- export { validateExpression, generateExpressionsComputation, executeExpressions, encodeDataSourceVariable, decodeDataSourceVariable, } from "./expression";
10
+ export { validateExpression, generateComputingExpressions, executeComputingExpressions, generateEffectfulExpression, executeEffectfulExpression, encodeDataSourceVariable, encodeVariablesMap, decodeDataSourceVariable, decodeVariablesMap, } from "./expression";
@@ -57,6 +57,16 @@ export declare const getPropsByInstanceId: (props: Map<string, {
57
57
  id: string;
58
58
  instanceId: string;
59
59
  required?: boolean | undefined;
60
+ } | {
61
+ name: string;
62
+ type: "action";
63
+ value: {
64
+ code: string;
65
+ type: "execute";
66
+ }[];
67
+ id: string;
68
+ instanceId: string;
69
+ required?: boolean | undefined;
60
70
  }>) => PropsByInstanceId;
61
71
  export declare const useInstanceProps: (instanceId: Instance["id"]) => Record<string, unknown>;
62
72
  export declare const usePropAsset: (instanceId: Instance["id"], name: string) => {