@webstudio-is/react-sdk 0.75.0 → 0.77.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.
Files changed (45) hide show
  1. package/lib/cjs/context.js +5 -1
  2. package/lib/cjs/css/normalize.js +51 -23
  3. package/lib/cjs/css/presets.js +111 -1
  4. package/lib/cjs/embed-template.js +68 -3
  5. package/lib/cjs/expression.js +213 -0
  6. package/lib/cjs/index.js +8 -1
  7. package/lib/cjs/props.js +28 -10
  8. package/lib/cjs/tree/create-elements-tree.js +14 -1
  9. package/lib/cjs/tree/root.js +38 -0
  10. package/lib/cjs/tree/webstudio-component.js +9 -2
  11. package/lib/context.js +5 -1
  12. package/lib/css/normalize.js +41 -23
  13. package/lib/css/presets.js +111 -1
  14. package/lib/embed-template.js +68 -3
  15. package/lib/expression.js +183 -0
  16. package/lib/index.js +15 -1
  17. package/lib/props.js +28 -10
  18. package/lib/tree/create-elements-tree.js +14 -1
  19. package/lib/tree/root.js +42 -1
  20. package/lib/tree/webstudio-component.js +9 -2
  21. package/lib/types/components/component-meta.d.ts +112 -0
  22. package/lib/types/context.d.ts +3 -0
  23. package/lib/types/css/normalize.d.ts +1836 -0
  24. package/lib/types/css/presets.d.ts +282 -0
  25. package/lib/types/embed-template.d.ts +512 -0
  26. package/lib/types/expression.d.ts +11 -0
  27. package/lib/types/expression.test.d.ts +1 -0
  28. package/lib/types/index.d.ts +2 -1
  29. package/lib/types/props.d.ts +8 -7
  30. package/lib/types/tree/create-elements-tree.d.ts +4 -2
  31. package/lib/types/tree/root.d.ts +6 -4
  32. package/lib/types/tree/webstudio-component.d.ts +1 -0
  33. package/package.json +10 -10
  34. package/src/context.tsx +11 -0
  35. package/src/css/normalize.ts +40 -23
  36. package/src/css/presets.ts +110 -0
  37. package/src/embed-template.test.ts +177 -1
  38. package/src/embed-template.ts +73 -2
  39. package/src/expression.test.ts +147 -0
  40. package/src/expression.ts +217 -0
  41. package/src/index.ts +8 -0
  42. package/src/props.ts +29 -10
  43. package/src/tree/create-elements-tree.tsx +20 -1
  44. package/src/tree/root.ts +61 -4
  45. package/src/tree/webstudio-component.tsx +7 -1
package/lib/cjs/index.js CHANGED
@@ -21,11 +21,17 @@ 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,
28
+ generateExpressionsComputation: () => import_expression.generateExpressionsComputation,
25
29
  getInstanceIdFromComponentProps: () => import_props.getInstanceIdFromComponentProps,
26
30
  stateCategories: () => import_component_meta.stateCategories,
31
+ useInstanceProps: () => import_props.useInstanceProps,
27
32
  usePropAsset: () => import_props.usePropAsset,
28
- usePropUrl: () => import_props.usePropUrl
33
+ usePropUrl: () => import_props.usePropUrl,
34
+ validateExpression: () => import_expression.validateExpression
29
35
  });
30
36
  module.exports = __toCommonJS(src_exports);
31
37
  __reExport(src_exports, require("./css"), module.exports);
@@ -37,3 +43,4 @@ var import_component_meta = require("./components/component-meta");
37
43
  __reExport(src_exports, require("./embed-template"), module.exports);
38
44
  var import_props = require("./props");
39
45
  var import_context = require("./context");
46
+ 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 propsByInstanceId = (0, import_react2.useStore)(propsByInstanceIdStore);
49
- const instanceProps = propsByInstanceId.get(instanceId);
50
- const instancePropsObject = {};
51
- if (instanceProps) {
52
- for (const prop of instanceProps) {
53
- if (prop.type !== "asset" && prop.type !== "page") {
54
- instancePropsObject[prop.name] = prop.value;
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
  }
@@ -21,15 +21,47 @@ __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");
28
29
  const InstanceRoot = ({
29
30
  data,
31
+ computeExpressions,
30
32
  Component,
31
33
  components
32
34
  }) => {
35
+ const dataSourceVariablesStoreRef = (0, import_react.useRef)(void 0);
36
+ if (dataSourceVariablesStoreRef.current === void 0) {
37
+ dataSourceVariablesStoreRef.current = (0, import_nanostores.atom)(/* @__PURE__ */ new Map());
38
+ }
39
+ const dataSourceVariablesStore = dataSourceVariablesStoreRef.current;
40
+ const dataSourceValuesStoreRef = (0, import_react.useRef)(void 0);
41
+ if (dataSourceValuesStoreRef.current === void 0) {
42
+ dataSourceValuesStoreRef.current = (0, import_nanostores.computed)(
43
+ dataSourceVariablesStore,
44
+ (dataSourceVariables) => {
45
+ const dataSourceValues = /* @__PURE__ */ new Map();
46
+ for (const [dataSourceId, dataSource] of data.build.dataSources) {
47
+ if (dataSource.type === "variable") {
48
+ const value = dataSourceVariables.get(dataSourceId) ?? dataSource.value.value;
49
+ dataSourceValues.set(dataSourceId, value);
50
+ }
51
+ }
52
+ try {
53
+ const result = computeExpressions(dataSourceValues);
54
+ for (const [id, value] of result) {
55
+ dataSourceValues.set(id, value);
56
+ }
57
+ } catch (error) {
58
+ console.error(error);
59
+ }
60
+ return dataSourceValues;
61
+ }
62
+ );
63
+ }
64
+ const dataSourceValuesStore = dataSourceValuesStoreRef.current;
33
65
  return (0, import_create_elements_tree.createElementsTree)({
34
66
  imageBaseUrl: data.params?.imageBaseUrl ?? "/",
35
67
  assetBaseUrl: data.params?.assetBaseUrl ?? "/",
@@ -40,6 +72,12 @@ const InstanceRoot = ({
40
72
  ),
41
73
  assetsStore: (0, import_nanostores.atom)(new Map(data.assets.map((asset) => [asset.id, asset]))),
42
74
  pagesStore: (0, import_nanostores.atom)(new Map(data.pages.map((page) => [page.id, page]))),
75
+ dataSourceValuesStore,
76
+ onDataSourceUpdate: (dataSourceId, value) => {
77
+ const dataSourceVariables = new Map(dataSourceVariablesStore.get());
78
+ dataSourceVariables.set(dataSourceId, value);
79
+ dataSourceVariablesStore.set(dataSourceVariables);
80
+ },
43
81
  Component: Component ?? import_webstudio_component.WebstudioComponent,
44
82
  components
45
83
  });
@@ -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)(instance.id);
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";
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
@@ -1,14 +1,22 @@
1
- import { borders, outline } from "./presets";
1
+ import * as presets from "./presets";
2
2
  const boxSizing = {
3
3
  property: "boxSizing",
4
4
  value: { type: "keyword", value: "border-box" }
5
5
  };
6
- const baseStyle = [boxSizing, ...borders, ...outline];
6
+ const baseStyle = [
7
+ boxSizing,
8
+ ...presets.borders,
9
+ ...presets.outline
10
+ ];
7
11
  const div = baseStyle;
8
12
  const address = baseStyle;
9
13
  const article = baseStyle;
10
14
  const aside = baseStyle;
11
- const figure = baseStyle;
15
+ const blockquote = [
16
+ ...baseStyle,
17
+ ...presets.blockquote
18
+ ];
19
+ const figure = [...baseStyle, ...presets.margins];
12
20
  const footer = baseStyle;
13
21
  const header = baseStyle;
14
22
  const main = baseStyle;
@@ -16,19 +24,19 @@ const nav = baseStyle;
16
24
  const section = baseStyle;
17
25
  const form = baseStyle;
18
26
  const label = baseStyle;
19
- const h1 = baseStyle;
20
- const h2 = baseStyle;
21
- const h3 = baseStyle;
22
- const h4 = baseStyle;
23
- const h5 = baseStyle;
24
- const h6 = baseStyle;
27
+ const h1 = [...baseStyle, ...presets.h1];
28
+ const h2 = [...baseStyle, ...presets.h2];
29
+ const h3 = [...baseStyle, ...presets.h3];
30
+ const h4 = [...baseStyle, ...presets.h4];
31
+ const h5 = [...baseStyle, ...presets.h5];
32
+ const h6 = [...baseStyle, ...presets.h6];
25
33
  const i = baseStyle;
26
34
  const img = baseStyle;
27
35
  const a = baseStyle;
28
36
  const li = baseStyle;
29
37
  const ul = baseStyle;
30
38
  const ol = baseStyle;
31
- const p = baseStyle;
39
+ const p = [...baseStyle, ...presets.verticalMargins];
32
40
  const span = baseStyle;
33
41
  const html = [
34
42
  /* 1 */
@@ -47,7 +55,7 @@ const html = [
47
55
  value: { type: "unit", value: 4, unit: "number" }
48
56
  },
49
57
  boxSizing,
50
- ...borders
58
+ ...presets.borders
51
59
  ];
52
60
  const body = [
53
61
  /* 1 */
@@ -72,11 +80,19 @@ const body = [
72
80
  property: "fontFamily",
73
81
  value: {
74
82
  type: "keyword",
75
- value: `system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'`
83
+ value: "Arial, sans-serif"
76
84
  }
77
85
  },
86
+ {
87
+ property: "fontSize",
88
+ value: { type: "unit", unit: "px", value: 16 }
89
+ },
90
+ {
91
+ property: "lineHeight",
92
+ value: { type: "unit", unit: "number", value: 1.2 }
93
+ },
78
94
  boxSizing,
79
- ...borders
95
+ ...presets.borders
80
96
  ];
81
97
  const hr = [
82
98
  /* 1 */
@@ -90,7 +106,8 @@ const hr = [
90
106
  value: { type: "keyword", value: "inherit" }
91
107
  },
92
108
  boxSizing,
93
- ...borders
109
+ ...presets.borders,
110
+ ...presets.margins
94
111
  ];
95
112
  const b = [
96
113
  {
@@ -98,7 +115,7 @@ const b = [
98
115
  value: { type: "keyword", value: "700" }
99
116
  },
100
117
  boxSizing,
101
- ...borders
118
+ ...presets.borders
102
119
  ];
103
120
  const strong = b;
104
121
  const code = [
@@ -116,7 +133,7 @@ const code = [
116
133
  value: { type: "unit", value: 1, unit: "em" }
117
134
  },
118
135
  boxSizing,
119
- ...borders
136
+ ...presets.borders
120
137
  ];
121
138
  const kbd = code;
122
139
  const samp = code;
@@ -127,7 +144,7 @@ const small = [
127
144
  value: { type: "unit", value: 80, unit: "%" }
128
145
  },
129
146
  boxSizing,
130
- ...borders
147
+ ...presets.borders
131
148
  ];
132
149
  const subSupBase = [
133
150
  {
@@ -147,7 +164,7 @@ const subSupBase = [
147
164
  value: { type: "keyword", value: "baseline" }
148
165
  },
149
166
  boxSizing,
150
- ...borders
167
+ ...presets.borders
151
168
  ];
152
169
  const sub = [
153
170
  ...subSupBase,
@@ -169,7 +186,7 @@ const table = [
169
186
  property: "textIndent",
170
187
  value: { type: "unit", value: 0, unit: "number" }
171
188
  },
172
- ...borders,
189
+ ...presets.borders,
173
190
  /* 2 */
174
191
  {
175
192
  property: "borderTopColor",
@@ -221,7 +238,7 @@ const buttonBase = [
221
238
  value: { type: "unit", value: 0, unit: "number" }
222
239
  },
223
240
  boxSizing,
224
- ...borders
241
+ ...presets.borders
225
242
  ];
226
243
  const input = buttonBase;
227
244
  const optgroup = buttonBase;
@@ -252,7 +269,7 @@ const legend = [
252
269
  value: { type: "unit", value: 0, unit: "number" }
253
270
  },
254
271
  boxSizing,
255
- ...borders
272
+ ...presets.borders
256
273
  ];
257
274
  const progress = [
258
275
  {
@@ -260,7 +277,7 @@ const progress = [
260
277
  value: { type: "keyword", value: "baseline" }
261
278
  },
262
279
  boxSizing,
263
- ...borders
280
+ ...presets.borders
264
281
  ];
265
282
  const summary = [
266
283
  {
@@ -268,7 +285,7 @@ const summary = [
268
285
  value: { type: "keyword", value: "list-item" }
269
286
  },
270
287
  boxSizing,
271
- ...borders
288
+ ...presets.borders
272
289
  ];
273
290
  export {
274
291
  a,
@@ -276,6 +293,7 @@ export {
276
293
  article,
277
294
  aside,
278
295
  b,
296
+ blockquote,
279
297
  body,
280
298
  button,
281
299
  code,
@@ -22,7 +22,117 @@ const outline = [
22
22
  value: { type: "unit", value: 1, unit: "px" }
23
23
  }
24
24
  ];
25
+ const margins = [
26
+ {
27
+ property: "marginTop",
28
+ value: { type: "unit", value: 0, unit: "px" }
29
+ },
30
+ {
31
+ property: "marginRight",
32
+ value: { type: "unit", value: 0, unit: "px" }
33
+ },
34
+ {
35
+ property: "marginBottom",
36
+ value: { type: "unit", value: 0, unit: "px" }
37
+ },
38
+ {
39
+ property: "marginLeft",
40
+ value: { type: "unit", value: 0, unit: "px" }
41
+ }
42
+ ];
43
+ const verticalMargins = [
44
+ {
45
+ property: "marginTop",
46
+ value: { type: "unit", value: 0, unit: "px" }
47
+ },
48
+ {
49
+ property: "marginBottom",
50
+ value: { type: "unit", value: 0, unit: "px" }
51
+ }
52
+ ];
53
+ const blockquote = [
54
+ ...margins,
55
+ {
56
+ property: "paddingTop",
57
+ value: { type: "unit", value: 10, unit: "px" }
58
+ },
59
+ {
60
+ property: "paddingBottom",
61
+ value: { type: "unit", value: 10, unit: "px" }
62
+ },
63
+ {
64
+ property: "paddingLeft",
65
+ value: { type: "unit", value: 20, unit: "px" }
66
+ },
67
+ {
68
+ property: "paddingRight",
69
+ value: { type: "unit", value: 20, unit: "px" }
70
+ },
71
+ {
72
+ property: "borderLeftWidth",
73
+ value: { type: "unit", value: 5, unit: "px" }
74
+ },
75
+ {
76
+ property: "borderLeftStyle",
77
+ value: { type: "keyword", value: "solid" }
78
+ },
79
+ {
80
+ property: "borderLeftColor",
81
+ value: { type: "rgb", r: 226, g: 226, b: 226, alpha: 1 }
82
+ }
83
+ ];
84
+ const h1 = [
85
+ ...verticalMargins,
86
+ {
87
+ property: "fontSize",
88
+ value: { type: "unit", value: 38, unit: "px" }
89
+ }
90
+ ];
91
+ const h2 = [
92
+ ...verticalMargins,
93
+ {
94
+ property: "fontSize",
95
+ value: { type: "unit", value: 32, unit: "px" }
96
+ }
97
+ ];
98
+ const h3 = [
99
+ ...verticalMargins,
100
+ {
101
+ property: "fontSize",
102
+ value: { type: "unit", value: 24, unit: "px" }
103
+ }
104
+ ];
105
+ const h4 = [
106
+ ...verticalMargins,
107
+ {
108
+ property: "fontSize",
109
+ value: { type: "unit", value: 18, unit: "px" }
110
+ }
111
+ ];
112
+ const h5 = [
113
+ ...verticalMargins,
114
+ {
115
+ property: "fontSize",
116
+ value: { type: "unit", value: 14, unit: "px" }
117
+ }
118
+ ];
119
+ const h6 = [
120
+ ...verticalMargins,
121
+ {
122
+ property: "fontSize",
123
+ value: { type: "unit", value: 12, unit: "px" }
124
+ }
125
+ ];
25
126
  export {
127
+ blockquote,
26
128
  borders,
27
- outline
129
+ h1,
130
+ h2,
131
+ h3,
132
+ h4,
133
+ h5,
134
+ h6,
135
+ margins,
136
+ outline,
137
+ verticalMargins
28
138
  };
@@ -1,29 +1,45 @@
1
1
  import { z } from "zod";
2
2
  import { nanoid } from "nanoid";
3
3
  import { StyleValue } from "@webstudio-is/css-data";
4
+ import { encodeDataSourceVariable, validateExpression } from "./expression";
4
5
  const EmbedTemplateText = z.object({
5
6
  type: z.literal("text"),
6
7
  value: z.string()
7
8
  });
9
+ const DataSourceRef = z.union([
10
+ z.object({
11
+ type: z.literal("variable"),
12
+ name: z.string()
13
+ }),
14
+ z.object({
15
+ type: z.literal("expression"),
16
+ name: z.string(),
17
+ code: z.string()
18
+ })
19
+ ]);
8
20
  const EmbedTemplateProp = z.union([
9
21
  z.object({
10
22
  type: z.literal("number"),
11
23
  name: z.string(),
24
+ dataSourceRef: z.optional(DataSourceRef),
12
25
  value: z.number()
13
26
  }),
14
27
  z.object({
15
28
  type: z.literal("string"),
16
29
  name: z.string(),
30
+ dataSourceRef: z.optional(DataSourceRef),
17
31
  value: z.string()
18
32
  }),
19
33
  z.object({
20
34
  type: z.literal("boolean"),
21
35
  name: z.string(),
36
+ dataSourceRef: z.optional(DataSourceRef),
22
37
  value: z.boolean()
23
38
  }),
24
39
  z.object({
25
40
  type: z.literal("string[]"),
26
41
  name: z.string(),
42
+ dataSourceRef: z.optional(DataSourceRef),
27
43
  value: z.array(z.string())
28
44
  })
29
45
  ]);
@@ -47,17 +63,52 @@ const EmbedTemplateInstance = z.lazy(
47
63
  const WsEmbedTemplate = z.lazy(
48
64
  () => z.array(z.union([EmbedTemplateInstance, EmbedTemplateText]))
49
65
  );
50
- const createInstancesFromTemplate = (treeTemplate, instances, props, styleSourceSelections, styleSources, styles, defaultBreakpointId) => {
66
+ const createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceByRef, styleSourceSelections, styleSources, styles, defaultBreakpointId) => {
51
67
  const parentChildren = [];
52
68
  for (const item of treeTemplate) {
53
69
  if (item.type === "instance") {
54
70
  const instanceId = nanoid();
55
71
  if (item.props) {
56
72
  for (const prop of item.props) {
73
+ const propId = nanoid();
74
+ if (prop.dataSourceRef === void 0) {
75
+ props.push({ id: propId, instanceId, ...prop });
76
+ continue;
77
+ }
78
+ let dataSource = dataSourceByRef.get(prop.dataSourceRef.name);
79
+ if (dataSource === void 0) {
80
+ const id = nanoid();
81
+ const { name: propName, dataSourceRef, ...rest } = prop;
82
+ if (dataSourceRef.type === "variable") {
83
+ dataSource = {
84
+ type: "variable",
85
+ id,
86
+ // the first instance where data source is appeared in becomes its scope
87
+ scopeInstanceId: instanceId,
88
+ name: dataSourceRef.name,
89
+ value: rest
90
+ };
91
+ dataSourceByRef.set(dataSourceRef.name, dataSource);
92
+ } else if (dataSourceRef.type === "expression") {
93
+ dataSource = {
94
+ type: "expression",
95
+ id,
96
+ scopeInstanceId: instanceId,
97
+ name: dataSourceRef.name,
98
+ code: dataSourceRef.code
99
+ };
100
+ dataSourceByRef.set(dataSourceRef.name, dataSource);
101
+ } else {
102
+ dataSourceRef;
103
+ continue;
104
+ }
105
+ }
57
106
  props.push({
58
- id: nanoid(),
107
+ id: propId,
59
108
  instanceId,
60
- ...prop
109
+ type: "dataSource",
110
+ name: prop.name,
111
+ value: dataSource.id
61
112
  });
62
113
  }
63
114
  }
@@ -93,6 +144,7 @@ const createInstancesFromTemplate = (treeTemplate, instances, props, styleSource
93
144
  item.children,
94
145
  instances,
95
146
  props,
147
+ dataSourceByRef,
96
148
  styleSourceSelections,
97
149
  styleSources,
98
150
  styles,
@@ -115,6 +167,7 @@ const createInstancesFromTemplate = (treeTemplate, instances, props, styleSource
115
167
  const generateDataFromEmbedTemplate = (treeTemplate, defaultBreakpointId) => {
116
168
  const instances = [];
117
169
  const props = [];
170
+ const dataSourceByRef = /* @__PURE__ */ new Map();
118
171
  const styleSourceSelections = [];
119
172
  const styleSources = [];
120
173
  const styles = [];
@@ -122,15 +175,27 @@ const generateDataFromEmbedTemplate = (treeTemplate, defaultBreakpointId) => {
122
175
  treeTemplate,
123
176
  instances,
124
177
  props,
178
+ dataSourceByRef,
125
179
  styleSourceSelections,
126
180
  styleSources,
127
181
  styles,
128
182
  defaultBreakpointId
129
183
  );
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
+ }
130
194
  return {
131
195
  children,
132
196
  instances,
133
197
  props,
198
+ dataSources,
134
199
  styleSourceSelections,
135
200
  styleSources,
136
201
  styles