@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
@@ -0,0 +1,11 @@
1
+ type TransformIdentifier = (id: string) => string;
2
+ export declare const validateExpression: (code: string, transformIdentifier?: TransformIdentifier) => string;
3
+ /**
4
+ * Generates a function body expecting map as _variables argument
5
+ * and outputing map of results
6
+ */
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>;
9
+ export declare const encodeDataSourceVariable: (id: string) => string;
10
+ export declare const decodeDataSourceVariable: (name: string) => string | undefined;
11
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -5,5 +5,6 @@ export * from "./app";
5
5
  export * from "./components/components-utils";
6
6
  export { type WsComponentPropsMeta, type WsComponentMeta, type ComponentState, type PresetStyle, componentCategories, stateCategories, defaultStates, } from "./components/component-meta";
7
7
  export * from "./embed-template";
8
- export { usePropUrl, usePropAsset, getInstanceIdFromComponentProps, } from "./props";
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";
@@ -50,14 +50,15 @@ export declare const getPropsByInstanceId: (props: Map<string, {
50
50
  id: string;
51
51
  instanceId: string;
52
52
  required?: boolean | undefined;
53
- }>) => PropsByInstanceId;
54
- export declare const useInstanceProps: (instanceId: Instance["id"]) => Record<string, number | boolean | string[] | ((string | {
55
- instanceId: string;
56
- pageId: string;
57
- }) & (string | {
53
+ } | {
54
+ name: string;
55
+ type: "dataSource";
56
+ value: string;
57
+ id: string;
58
58
  instanceId: string;
59
- pageId: string;
60
- } | undefined))>;
59
+ required?: boolean | undefined;
60
+ }>) => PropsByInstanceId;
61
+ export declare const useInstanceProps: (instanceId: Instance["id"]) => Record<string, unknown>;
61
62
  export declare const usePropAsset: (instanceId: Instance["id"], name: string) => {
62
63
  name: string;
63
64
  type: "font";
@@ -1,12 +1,12 @@
1
1
  import { type ComponentProps } from "react";
2
2
  import type { ReadableAtom } from "nanostores";
3
3
  import type { Assets } from "@webstudio-is/asset-uploader";
4
- import type { Instance, Instances } from "@webstudio-is/project-build";
4
+ import type { DataSource, Instance, Instances } from "@webstudio-is/project-build";
5
5
  import type { Components } from "../components/components-utils";
6
6
  import { type Params } from "../context";
7
7
  import type { Pages, PropsByInstanceId } from "../props";
8
8
  import type { WebstudioComponent } from "./webstudio-component";
9
- export declare const createElementsTree: ({ renderer, imageBaseUrl, assetBaseUrl, instances, rootInstanceId, propsByInstanceIdStore, assetsStore, pagesStore, Component, components, }: Params & {
9
+ export declare const createElementsTree: ({ renderer, imageBaseUrl, assetBaseUrl, instances, rootInstanceId, propsByInstanceIdStore, assetsStore, pagesStore, dataSourceValuesStore, onDataSourceUpdate, Component, components, }: Params & {
10
10
  instances: Map<string, {
11
11
  type: "instance";
12
12
  id: string;
@@ -24,6 +24,8 @@ export declare const createElementsTree: ({ renderer, imageBaseUrl, assetBaseUrl
24
24
  propsByInstanceIdStore: ReadableAtom<PropsByInstanceId>;
25
25
  assetsStore: ReadableAtom<Assets>;
26
26
  pagesStore: ReadableAtom<Pages>;
27
+ dataSourceValuesStore: ReadableAtom<Map<DataSource["id"], unknown>>;
28
+ onDataSourceUpdate: (dataSourceId: DataSource["id"], value: unknown) => void;
27
29
  Component: (props: ComponentProps<typeof WebstudioComponent>) => JSX.Element;
28
30
  components: Components;
29
31
  }) => JSX.Element | null;
@@ -1,5 +1,5 @@
1
- import type { ComponentProps } from "react";
2
- import type { Build, Page } from "@webstudio-is/project-build";
1
+ import { type ComponentProps } from "react";
2
+ import { type Build, type Page, DataSource } from "@webstudio-is/project-build";
3
3
  import type { Asset } from "@webstudio-is/asset-uploader";
4
4
  import { WebstudioComponent } from "./webstudio-component";
5
5
  import type { Components } from "../components/components-utils";
@@ -12,12 +12,14 @@ export type Data = {
12
12
  params?: Params;
13
13
  };
14
14
  export type RootPropsData = Omit<Data, "build"> & {
15
- build: Pick<Data["build"], "instances" | "props">;
15
+ build: Pick<Data["build"], "instances" | "props" | "dataSources">;
16
16
  };
17
+ type DataSourceValues = Map<DataSource["id"], unknown>;
17
18
  type RootProps = {
18
19
  data: RootPropsData;
20
+ computeExpressions: (values: DataSourceValues) => DataSourceValues;
19
21
  Component?: (props: ComponentProps<typeof WebstudioComponent>) => JSX.Element;
20
22
  components: Components;
21
23
  };
22
- export declare const InstanceRoot: ({ data, Component, components, }: RootProps) => JSX.Element | null;
24
+ export declare const InstanceRoot: ({ data, computeExpressions, Component, components, }: RootProps) => JSX.Element | null;
23
25
  export {};
@@ -11,5 +11,6 @@ type WebstudioComponentProps = {
11
11
  export declare const WebstudioComponent: ({ instance, instanceSelector, children, components, ...rest }: WebstudioComponentProps) => JSX.Element;
12
12
  export declare const idAttribute = "data-ws-id";
13
13
  export declare const componentAttribute = "data-ws-component";
14
+ export declare const showAttribute = "data-ws-show";
14
15
  export declare const collapsedAttribute = "data-ws-collapsed";
15
16
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webstudio-is/react-sdk",
3
- "version": "0.75.0",
3
+ "version": "0.77.0",
4
4
  "description": "Webstudio JavaScript / TypeScript API",
5
5
  "author": "Webstudio <github@webstudio.is>",
6
6
  "homepage": "https://webstudio.is",
@@ -30,15 +30,16 @@
30
30
  "@nanostores/react": "^0.4.1",
31
31
  "detect-font": "^0.1.5",
32
32
  "html-tags": "^3.2.0",
33
+ "jsep": "^1.3.8",
33
34
  "nanoevents": "^7.0.1",
34
- "nanoid": "^3.2.0",
35
+ "nanoid": "^3.3.6",
35
36
  "nanostores": "^0.7.1",
36
- "@webstudio-is/asset-uploader": "^0.75.0",
37
- "@webstudio-is/css-data": "^0.75.0",
38
- "@webstudio-is/css-engine": "^0.75.0",
39
- "@webstudio-is/fonts": "^0.75.0",
40
- "@webstudio-is/generate-arg-types": "^0.75.0",
41
- "@webstudio-is/project-build": "^0.75.0"
37
+ "@webstudio-is/asset-uploader": "^0.77.0",
38
+ "@webstudio-is/css-data": "^0.77.0",
39
+ "@webstudio-is/css-engine": "^0.77.0",
40
+ "@webstudio-is/fonts": "^0.77.0",
41
+ "@webstudio-is/generate-arg-types": "^0.77.0",
42
+ "@webstudio-is/project-build": "^0.77.0"
42
43
  },
43
44
  "exports": {
44
45
  ".": {
@@ -69,7 +70,6 @@
69
70
  "dts": "tsc --project tsconfig.dts.json",
70
71
  "typecheck": "tsc --noEmit --emitDeclarationOnly false",
71
72
  "test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests",
72
- "lint": "eslint ./src --ext .ts,.tsx --max-warnings 0",
73
- "checks": "pnpm typecheck && pnpm lint && pnpm test"
73
+ "checks": "pnpm typecheck && pnpm test"
74
74
  }
75
75
  }
package/src/context.tsx CHANGED
@@ -1,6 +1,7 @@
1
1
  import { type ReadableAtom, atom } from "nanostores";
2
2
  import { createContext } from "react";
3
3
  import type { Assets } from "@webstudio-is/asset-uploader";
4
+ import type { DataSource, Instance, Prop } from "@webstudio-is/project-build";
4
5
  import type { Pages, PropsByInstanceId } from "./props";
5
6
 
6
7
  export type Params = {
@@ -35,6 +36,12 @@ export const ReactSdkContext = createContext<
35
36
  propsByInstanceIdStore: ReadableAtom<PropsByInstanceId>;
36
37
  assetsStore: ReadableAtom<Assets>;
37
38
  pagesStore: ReadableAtom<Pages>;
39
+ dataSourceValuesStore: ReadableAtom<Map<DataSource["id"], unknown>>;
40
+ setDataSourceValue: (
41
+ instanceId: Instance["id"],
42
+ prop: Prop["name"],
43
+ value: unknown
44
+ ) => void;
38
45
  }
39
46
  >({
40
47
  imageBaseUrl: "/",
@@ -42,4 +49,8 @@ export const ReactSdkContext = createContext<
42
49
  propsByInstanceIdStore: atom(new Map()),
43
50
  assetsStore: atom(new Map()),
44
51
  pagesStore: atom(new Map()),
52
+ dataSourceValuesStore: atom(new Map()),
53
+ setDataSourceValue: () => {
54
+ throw Error("React SDK setDataSourceValue is not implemented");
55
+ },
45
56
  });
@@ -16,7 +16,7 @@
16
16
  */
17
17
 
18
18
  // webstudio custom opinionated presets
19
- import { borders, outline } from "./presets";
19
+ import * as presets from "./presets";
20
20
  import type { EmbedTemplateStyleDecl } from "../embed-template";
21
21
 
22
22
  export type Styles = EmbedTemplateStyleDecl[];
@@ -37,13 +37,21 @@ const boxSizing = {
37
37
  * box-sizing: border-box;
38
38
  }
39
39
  */
40
- const baseStyle = [boxSizing, ...borders, ...outline] satisfies Styles;
40
+ const baseStyle = [
41
+ boxSizing,
42
+ ...presets.borders,
43
+ ...presets.outline,
44
+ ] satisfies Styles;
41
45
 
42
46
  export const div = baseStyle;
43
47
  export const address = baseStyle;
44
48
  export const article = baseStyle;
45
49
  export const aside = baseStyle;
46
- export const figure = baseStyle;
50
+ export const blockquote = [
51
+ ...baseStyle,
52
+ ...presets.blockquote,
53
+ ] satisfies Styles;
54
+ export const figure = [...baseStyle, ...presets.margins] satisfies Styles;
47
55
  export const footer = baseStyle;
48
56
  export const header = baseStyle;
49
57
  export const main = baseStyle;
@@ -52,12 +60,12 @@ export const section = baseStyle;
52
60
  export const form = baseStyle;
53
61
  export const label = baseStyle;
54
62
 
55
- export const h1 = baseStyle;
56
- export const h2 = baseStyle;
57
- export const h3 = baseStyle;
58
- export const h4 = baseStyle;
59
- export const h5 = baseStyle;
60
- export const h6 = baseStyle;
63
+ export const h1 = [...baseStyle, ...presets.h1] satisfies Styles;
64
+ export const h2 = [...baseStyle, ...presets.h2] satisfies Styles;
65
+ export const h3 = [...baseStyle, ...presets.h3] satisfies Styles;
66
+ export const h4 = [...baseStyle, ...presets.h4] satisfies Styles;
67
+ export const h5 = [...baseStyle, ...presets.h5] satisfies Styles;
68
+ export const h6 = [...baseStyle, ...presets.h6] satisfies Styles;
61
69
 
62
70
  export const i = baseStyle;
63
71
 
@@ -68,7 +76,7 @@ export const li = baseStyle;
68
76
  export const ul = baseStyle;
69
77
  export const ol = baseStyle;
70
78
 
71
- export const p = baseStyle;
79
+ export const p = [...baseStyle, ...presets.verticalMargins];
72
80
  export const span = baseStyle;
73
81
 
74
82
  // @todo for now not applied to html, as we don't have html element
@@ -94,7 +102,7 @@ export const html = [
94
102
  value: { type: "unit", value: 4, unit: "number" },
95
103
  },
96
104
  boxSizing,
97
- ...borders,
105
+ ...presets.borders,
98
106
  ] satisfies Styles;
99
107
 
100
108
  /**
@@ -124,11 +132,19 @@ export const body = [
124
132
  property: "fontFamily",
125
133
  value: {
126
134
  type: "keyword",
127
- value: `system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'`,
135
+ value: "Arial, sans-serif",
128
136
  },
129
137
  },
138
+ {
139
+ property: "fontSize",
140
+ value: { type: "unit", unit: "px", value: 16 },
141
+ },
142
+ {
143
+ property: "lineHeight",
144
+ value: { type: "unit", unit: "number", value: 1.2 },
145
+ },
130
146
  boxSizing,
131
- ...borders,
147
+ ...presets.borders,
132
148
  ] satisfies Styles;
133
149
 
134
150
  /**
@@ -147,7 +163,8 @@ export const hr = [
147
163
  value: { type: "keyword", value: "inherit" },
148
164
  },
149
165
  boxSizing,
150
- ...borders,
166
+ ...presets.borders,
167
+ ...presets.margins,
151
168
  ] satisfies Styles;
152
169
 
153
170
  /**
@@ -169,7 +186,7 @@ export const b = [
169
186
  value: { type: "keyword", value: "700" },
170
187
  },
171
188
  boxSizing,
172
- ...borders,
189
+ ...presets.borders,
173
190
  ] satisfies Styles;
174
191
  export const strong = b;
175
192
 
@@ -192,7 +209,7 @@ export const code = [
192
209
  value: { type: "unit", value: 1, unit: "em" },
193
210
  },
194
211
  boxSizing,
195
- ...borders,
212
+ ...presets.borders,
196
213
  ] satisfies Styles;
197
214
 
198
215
  export const kbd = code;
@@ -209,7 +226,7 @@ export const small = [
209
226
  value: { type: "unit", value: 80, unit: "%" },
210
227
  },
211
228
  boxSizing,
212
- ...borders,
229
+ ...presets.borders,
213
230
  ] satisfies Styles;
214
231
 
215
232
  /**
@@ -234,7 +251,7 @@ const subSupBase = [
234
251
  value: { type: "keyword", value: "baseline" },
235
252
  },
236
253
  boxSizing,
237
- ...borders,
254
+ ...presets.borders,
238
255
  ] satisfies Styles;
239
256
 
240
257
  export const sub = [
@@ -269,7 +286,7 @@ export const table = [
269
286
  property: "textIndent",
270
287
  value: { type: "unit", value: 0, unit: "number" },
271
288
  },
272
- ...borders,
289
+ ...presets.borders,
273
290
  /* 2 */
274
291
  {
275
292
  property: "borderTopColor",
@@ -332,7 +349,7 @@ const buttonBase = [
332
349
  value: { type: "unit", value: 0, unit: "number" },
333
350
  },
334
351
  boxSizing,
335
- ...borders,
352
+ ...presets.borders,
336
353
  ] satisfies Styles;
337
354
 
338
355
  export const input = buttonBase;
@@ -419,7 +436,7 @@ export const legend = [
419
436
  value: { type: "unit", value: 0, unit: "number" },
420
437
  },
421
438
  boxSizing,
422
- ...borders,
439
+ ...presets.borders,
423
440
  ] satisfies Styles;
424
441
 
425
442
  /**
@@ -432,7 +449,7 @@ export const progress = [
432
449
  value: { type: "keyword", value: "baseline" },
433
450
  },
434
451
  boxSizing,
435
- ...borders,
452
+ ...presets.borders,
436
453
  ] satisfies Styles;
437
454
 
438
455
  /**
@@ -495,5 +512,5 @@ export const summary = [
495
512
  value: { type: "keyword", value: "list-item" },
496
513
  },
497
514
  boxSizing,
498
- ...borders,
515
+ ...presets.borders,
499
516
  ] satisfies Styles;
@@ -25,3 +25,113 @@ export const outline: Styles = [
25
25
  value: { type: "unit", value: 1, unit: "px" },
26
26
  },
27
27
  ];
28
+
29
+ export const margins = [
30
+ {
31
+ property: "marginTop",
32
+ value: { type: "unit", value: 0, unit: "px" },
33
+ },
34
+ {
35
+ property: "marginRight",
36
+ value: { type: "unit", value: 0, unit: "px" },
37
+ },
38
+ {
39
+ property: "marginBottom",
40
+ value: { type: "unit", value: 0, unit: "px" },
41
+ },
42
+ {
43
+ property: "marginLeft",
44
+ value: { type: "unit", value: 0, unit: "px" },
45
+ },
46
+ ] satisfies Styles;
47
+
48
+ export const verticalMargins = [
49
+ {
50
+ property: "marginTop",
51
+ value: { type: "unit", value: 0, unit: "px" },
52
+ },
53
+ {
54
+ property: "marginBottom",
55
+ value: { type: "unit", value: 0, unit: "px" },
56
+ },
57
+ ] satisfies Styles;
58
+
59
+ export const blockquote = [
60
+ ...margins,
61
+ {
62
+ property: "paddingTop",
63
+ value: { type: "unit", value: 10, unit: "px" },
64
+ },
65
+ {
66
+ property: "paddingBottom",
67
+ value: { type: "unit", value: 10, unit: "px" },
68
+ },
69
+ {
70
+ property: "paddingLeft",
71
+ value: { type: "unit", value: 20, unit: "px" },
72
+ },
73
+ {
74
+ property: "paddingRight",
75
+ value: { type: "unit", value: 20, unit: "px" },
76
+ },
77
+ {
78
+ property: "borderLeftWidth",
79
+ value: { type: "unit", value: 5, unit: "px" },
80
+ },
81
+ {
82
+ property: "borderLeftStyle",
83
+ value: { type: "keyword", value: "solid" },
84
+ },
85
+ {
86
+ property: "borderLeftColor",
87
+ value: { type: "rgb", r: 226, g: 226, b: 226, alpha: 1 },
88
+ },
89
+ ] satisfies Styles;
90
+
91
+ export const h1 = [
92
+ ...verticalMargins,
93
+ {
94
+ property: "fontSize",
95
+ value: { type: "unit", value: 38, unit: "px" },
96
+ },
97
+ ] satisfies Styles;
98
+
99
+ export const h2 = [
100
+ ...verticalMargins,
101
+ {
102
+ property: "fontSize",
103
+ value: { type: "unit", value: 32, unit: "px" },
104
+ },
105
+ ] satisfies Styles;
106
+
107
+ export const h3 = [
108
+ ...verticalMargins,
109
+ {
110
+ property: "fontSize",
111
+ value: { type: "unit", value: 24, unit: "px" },
112
+ },
113
+ ] satisfies Styles;
114
+
115
+ export const h4 = [
116
+ ...verticalMargins,
117
+ {
118
+ property: "fontSize",
119
+ value: { type: "unit", value: 18, unit: "px" },
120
+ },
121
+ ] satisfies Styles;
122
+
123
+ export const h5 = [
124
+ ...verticalMargins,
125
+ {
126
+ property: "fontSize",
127
+ value: { type: "unit", value: 14, unit: "px" },
128
+ },
129
+ ] satisfies Styles;
130
+
131
+ export const h6 = [
132
+ ...verticalMargins,
133
+ {
134
+ property: "fontSize",
135
+ value: { type: "unit", value: 12, unit: "px" },
136
+ },
137
+ ] satisfies Styles;
@@ -1,7 +1,8 @@
1
1
  import { expect, test } from "@jest/globals";
2
2
  import { generateDataFromEmbedTemplate } from "./embed-template";
3
+ import { showAttribute } from "./tree";
3
4
 
4
- const expectString = expect.any(String) as unknown as string;
5
+ const expectString = expect.any(String);
5
6
 
6
7
  const defaultBreakpointId = "base";
7
8
 
@@ -44,6 +45,7 @@ test("generate data for embedding from instances and text", () => {
44
45
  },
45
46
  ],
46
47
  props: [],
48
+ dataSources: [],
47
49
  styleSourceSelections: [],
48
50
  styleSources: [],
49
51
  styles: [],
@@ -112,6 +114,7 @@ test("generate data for embedding from props", () => {
112
114
  value: "value3",
113
115
  },
114
116
  ],
117
+ dataSources: [],
115
118
  styleSourceSelections: [],
116
119
  styleSources: [],
117
120
  styles: [],
@@ -163,6 +166,7 @@ test("generate data for embedding from styles", () => {
163
166
  },
164
167
  ],
165
168
  props: [],
169
+ dataSources: [],
166
170
  styleSourceSelections: [
167
171
  {
168
172
  instanceId: expectString,
@@ -208,3 +212,175 @@ test("generate data for embedding from styles", () => {
208
212
  ],
209
213
  });
210
214
  });
215
+
216
+ test("generate data for embedding from props bound to data source variables", () => {
217
+ expect(
218
+ generateDataFromEmbedTemplate(
219
+ [
220
+ {
221
+ type: "instance",
222
+ component: "Box1",
223
+ props: [
224
+ {
225
+ type: "boolean",
226
+ name: "showOtherBox",
227
+ value: false,
228
+ dataSourceRef: {
229
+ type: "variable",
230
+ name: "showOtherBoxDataSource",
231
+ },
232
+ },
233
+ ],
234
+ children: [],
235
+ },
236
+ {
237
+ type: "instance",
238
+ component: "Box2",
239
+ props: [
240
+ {
241
+ type: "boolean",
242
+ name: showAttribute,
243
+ value: false,
244
+ dataSourceRef: {
245
+ type: "variable",
246
+ name: "showOtherBoxDataSource",
247
+ },
248
+ },
249
+ ],
250
+ children: [],
251
+ },
252
+ ],
253
+ defaultBreakpointId
254
+ )
255
+ ).toEqual({
256
+ children: [
257
+ { type: "id", value: expectString },
258
+ { type: "id", value: expectString },
259
+ ],
260
+ instances: [
261
+ { type: "instance", id: expectString, component: "Box1", children: [] },
262
+ { type: "instance", id: expectString, component: "Box2", children: [] },
263
+ ],
264
+ props: [
265
+ {
266
+ id: expectString,
267
+ instanceId: expectString,
268
+ type: "dataSource",
269
+ name: "showOtherBox",
270
+ value: expectString,
271
+ },
272
+ {
273
+ id: expectString,
274
+ instanceId: expectString,
275
+ type: "dataSource",
276
+ name: showAttribute,
277
+ value: expectString,
278
+ },
279
+ ],
280
+ dataSources: [
281
+ {
282
+ type: "variable",
283
+ id: expectString,
284
+ scopeInstanceId: expectString,
285
+ name: "showOtherBoxDataSource",
286
+ value: {
287
+ type: "boolean",
288
+ value: false,
289
+ },
290
+ },
291
+ ],
292
+ styleSourceSelections: [],
293
+ styleSources: [],
294
+ styles: [],
295
+ });
296
+ });
297
+
298
+ test("generate data for embedding from props bound to data source expressions", () => {
299
+ expect(
300
+ generateDataFromEmbedTemplate(
301
+ [
302
+ {
303
+ type: "instance",
304
+ component: "Box1",
305
+ props: [
306
+ {
307
+ type: "string",
308
+ name: "state",
309
+ value: "initial",
310
+ dataSourceRef: {
311
+ type: "variable",
312
+ name: "boxState",
313
+ },
314
+ },
315
+ ],
316
+ children: [],
317
+ },
318
+ {
319
+ type: "instance",
320
+ component: "Box2",
321
+ props: [
322
+ {
323
+ type: "boolean",
324
+ name: showAttribute,
325
+ value: false,
326
+ dataSourceRef: {
327
+ type: "expression",
328
+ name: "boxStateSuccess",
329
+ code: `boxState === 'success'`,
330
+ },
331
+ },
332
+ ],
333
+ children: [],
334
+ },
335
+ ],
336
+ defaultBreakpointId
337
+ )
338
+ ).toEqual({
339
+ children: [
340
+ { type: "id", value: expectString },
341
+ { type: "id", value: expectString },
342
+ ],
343
+ instances: [
344
+ { type: "instance", id: expectString, component: "Box1", children: [] },
345
+ { type: "instance", id: expectString, component: "Box2", children: [] },
346
+ ],
347
+ props: [
348
+ {
349
+ id: expectString,
350
+ instanceId: expectString,
351
+ type: "dataSource",
352
+ name: "state",
353
+ value: expectString,
354
+ },
355
+ {
356
+ id: expectString,
357
+ instanceId: expectString,
358
+ type: "dataSource",
359
+ name: showAttribute,
360
+ value: expectString,
361
+ },
362
+ ],
363
+ dataSources: [
364
+ {
365
+ type: "variable",
366
+ id: expectString,
367
+ scopeInstanceId: expectString,
368
+ name: "boxState",
369
+ value: {
370
+ type: "string",
371
+ value: "initial",
372
+ },
373
+ },
374
+ {
375
+ type: "expression",
376
+ id: expectString,
377
+ scopeInstanceId: expectString,
378
+ name: "boxStateSuccess",
379
+ code: expect.stringMatching(/\$ws\$dataSource\$\w+ === 'success'/),
380
+ },
381
+ ],
382
+ styleSourceSelections: [],
383
+ styleSources: [],
384
+ styles: [],
385
+ });
386
+ });