@webstudio-is/react-sdk 0.82.0 → 0.84.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 (71) hide show
  1. package/LICENSE +661 -21
  2. package/lib/cjs/component-renderer.js +125 -0
  3. package/lib/cjs/components/component-meta.js +10 -0
  4. package/lib/cjs/components/components-utils.js +1 -0
  5. package/lib/cjs/context.js +2 -1
  6. package/lib/cjs/css/index.js +0 -1
  7. package/lib/cjs/css/style-rules.js +1 -1
  8. package/lib/cjs/embed-template.js +130 -55
  9. package/lib/cjs/expression.js +47 -4
  10. package/lib/cjs/hook.js +34 -0
  11. package/lib/cjs/index.js +7 -0
  12. package/lib/cjs/instance-utils.js +65 -0
  13. package/lib/cjs/props.js +18 -3
  14. package/lib/cjs/tree/create-elements-tree.js +5 -4
  15. package/lib/cjs/tree/root.js +7 -2
  16. package/lib/cjs/tree/webstudio-component.js +26 -10
  17. package/lib/component-renderer.js +111 -0
  18. package/lib/components/component-meta.js +10 -0
  19. package/lib/components/components-utils.js +1 -0
  20. package/lib/context.js +2 -1
  21. package/lib/css/index.js +0 -1
  22. package/lib/css/style-rules.js +1 -1
  23. package/lib/embed-template.js +138 -55
  24. package/lib/expression.js +47 -4
  25. package/lib/hook.js +14 -0
  26. package/lib/index.js +10 -1
  27. package/lib/instance-utils.js +45 -0
  28. package/lib/props.js +19 -4
  29. package/lib/tree/create-elements-tree.js +8 -5
  30. package/lib/tree/root.js +14 -4
  31. package/lib/tree/webstudio-component.js +27 -11
  32. package/lib/types/app/root.d.ts +1 -2
  33. package/lib/types/component-renderer.d.ts +8 -0
  34. package/lib/types/components/component-meta.d.ts +14 -8
  35. package/lib/types/context.d.ts +3 -1
  36. package/lib/types/css/css.d.ts +19 -19
  37. package/lib/types/css/global-rules.d.ts +19 -19
  38. package/lib/types/css/index.d.ts +0 -1
  39. package/lib/types/css/normalize.d.ts +47 -47
  40. package/lib/types/embed-template.d.ts +297 -174
  41. package/lib/types/expression.d.ts +3 -2
  42. package/lib/types/hook.d.ts +31 -0
  43. package/lib/types/index.d.ts +5 -2
  44. package/lib/types/instance-utils.d.ts +16 -0
  45. package/lib/types/instance-utils.test.d.ts +1 -0
  46. package/lib/types/props.d.ts +48 -46
  47. package/lib/types/tree/create-elements-tree.d.ts +9 -6
  48. package/lib/types/tree/root.d.ts +8 -5
  49. package/lib/types/tree/webstudio-component.d.ts +16 -7
  50. package/package.json +18 -19
  51. package/src/component-renderer.tsx +117 -0
  52. package/src/components/component-meta.ts +10 -0
  53. package/src/context.tsx +4 -0
  54. package/src/css/index.ts +0 -1
  55. package/src/css/style-rules.ts +1 -1
  56. package/src/embed-template.test.ts +113 -26
  57. package/src/embed-template.ts +149 -56
  58. package/src/expression.test.ts +74 -6
  59. package/src/expression.ts +55 -2
  60. package/src/hook.ts +42 -0
  61. package/src/index.ts +5 -0
  62. package/src/instance-utils.test.ts +89 -0
  63. package/src/instance-utils.ts +65 -0
  64. package/src/props.ts +19 -2
  65. package/src/tree/create-elements-tree.tsx +25 -8
  66. package/src/tree/root.ts +22 -3
  67. package/src/tree/webstudio-component.tsx +42 -14
  68. package/lib/cjs/css/get-browser-style.js +0 -83
  69. package/lib/css/get-browser-style.js +0 -65
  70. package/lib/types/css/get-browser-style.d.ts +0 -2
  71. package/src/css/get-browser-style.ts +0 -81
package/lib/cjs/props.js CHANGED
@@ -18,6 +18,7 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var props_exports = {};
20
20
  __export(props_exports, {
21
+ getIndexWithinAncestorFromComponentProps: () => getIndexWithinAncestorFromComponentProps,
21
22
  getInstanceIdFromComponentProps: () => getInstanceIdFromComponentProps,
22
23
  getPropsByInstanceId: () => getPropsByInstanceId,
23
24
  resolveUrlProp: () => resolveUrlProp,
@@ -49,13 +50,18 @@ const useInstanceProps = (instanceId) => {
49
50
  dataSourceValuesStore,
50
51
  executeEffectfulExpression,
51
52
  setDataSourceValues,
52
- renderer
53
+ renderer,
54
+ indexesWithinAncestors
53
55
  } = (0, import_react.useContext)(import_context.ReactSdkContext);
56
+ const index = indexesWithinAncestors.get(instanceId);
54
57
  const instancePropsObjectStore = (0, import_react.useMemo)(() => {
55
58
  return (0, import_nanostores.computed)(
56
59
  [propsByInstanceIdStore, dataSourceValuesStore],
57
60
  (propsByInstanceId, dataSourceValues) => {
58
61
  const instancePropsObject2 = {};
62
+ if (index !== void 0) {
63
+ instancePropsObject2[import_webstudio_component.indexAttribute] = index.toString();
64
+ }
59
65
  const instanceProps = propsByInstanceId.get(instanceId);
60
66
  if (instanceProps === void 0) {
61
67
  return instancePropsObject2;
@@ -73,14 +79,19 @@ const useInstanceProps = (instanceId) => {
73
79
  continue;
74
80
  }
75
81
  if (prop.type === "action") {
76
- instancePropsObject2[prop.name] = () => {
82
+ instancePropsObject2[prop.name] = (...args) => {
77
83
  if (renderer === "canvas") {
78
84
  return;
79
85
  }
80
86
  for (const value of prop.value) {
81
87
  if (value.type === "execute") {
88
+ const argsMap = /* @__PURE__ */ new Map();
89
+ for (const [i, name] of value.args.entries()) {
90
+ argsMap.set(name, args[i]);
91
+ }
82
92
  const newValues = executeEffectfulExpression(
83
93
  value.code,
94
+ argsMap,
84
95
  dataSourceValues
85
96
  );
86
97
  setDataSourceValues(newValues);
@@ -100,7 +111,8 @@ const useInstanceProps = (instanceId) => {
100
111
  instanceId,
101
112
  renderer,
102
113
  executeEffectfulExpression,
103
- setDataSourceValues
114
+ setDataSourceValues,
115
+ index
104
116
  ]);
105
117
  const instancePropsObject = (0, import_react2.useStore)(instancePropsObjectStore);
106
118
  return instancePropsObject;
@@ -187,3 +199,6 @@ const usePropUrl = (instanceId, name) => {
187
199
  const getInstanceIdFromComponentProps = (props) => {
188
200
  return props[import_webstudio_component.idAttribute];
189
201
  };
202
+ const getIndexWithinAncestorFromComponentProps = (props) => {
203
+ return props[import_webstudio_component.indexAttribute];
204
+ };
@@ -23,7 +23,6 @@ __export(create_elements_tree_exports, {
23
23
  module.exports = __toCommonJS(create_elements_tree_exports);
24
24
  var import_jsx_runtime = require("react/jsx-runtime");
25
25
  var import_react = require("react");
26
- var import_react2 = require("@remix-run/react");
27
26
  var import_context = require("../context");
28
27
  const createElementsTree = ({
29
28
  renderer,
@@ -37,8 +36,10 @@ const createElementsTree = ({
37
36
  dataSourceValuesStore,
38
37
  executeEffectfulExpression,
39
38
  onDataSourceUpdate,
39
+ indexesWithinAncestors,
40
40
  Component,
41
- components
41
+ components,
42
+ scripts
42
43
  }) => {
43
44
  const rootInstance = instances.get(rootInstanceId);
44
45
  if (rootInstance === void 0) {
@@ -59,8 +60,7 @@ const createElementsTree = ({
59
60
  children: [
60
61
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.Fragment, { children: [
61
62
  children,
62
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react2.ScrollRestoration, {}),
63
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react2.Scripts, {})
63
+ scripts
64
64
  ] }, "children")
65
65
  ],
66
66
  components
@@ -76,6 +76,7 @@ const createElementsTree = ({
76
76
  renderer,
77
77
  imageBaseUrl,
78
78
  assetBaseUrl,
79
+ indexesWithinAncestors,
79
80
  executeEffectfulExpression,
80
81
  setDataSourceValues: onDataSourceUpdate,
81
82
  setBoundDataSourceValue: (instanceId, propName, value) => {
@@ -23,15 +23,18 @@ __export(root_exports, {
23
23
  module.exports = __toCommonJS(root_exports);
24
24
  var import_react = require("react");
25
25
  var import_nanostores = require("nanostores");
26
+ var import_project_build = require("@webstudio-is/project-build");
26
27
  var import_create_elements_tree = require("./create-elements-tree");
27
28
  var import_webstudio_component = require("./webstudio-component");
28
29
  var import_props = require("../props");
29
30
  const InstanceRoot = ({
30
31
  data,
32
+ indexesWithinAncestors,
31
33
  executeComputingExpressions,
32
34
  executeEffectfulExpression,
33
35
  Component,
34
- components
36
+ components,
37
+ scripts
35
38
  }) => {
36
39
  const dataSourceVariablesStoreRef = (0, import_react.useRef)(void 0);
37
40
  if (dataSourceVariablesStoreRef.current === void 0) {
@@ -83,10 +86,12 @@ const InstanceRoot = ({
83
86
  ),
84
87
  assetsStore: (0, import_nanostores.atom)(new Map(data.assets.map((asset) => [asset.id, asset]))),
85
88
  pagesStore: (0, import_nanostores.atom)(new Map(data.pages.map((page) => [page.id, page]))),
89
+ indexesWithinAncestors,
86
90
  executeEffectfulExpression,
87
91
  dataSourceValuesStore,
88
92
  onDataSourceUpdate,
89
93
  Component: Component ?? import_webstudio_component.WebstudioComponent,
90
- components
94
+ components,
95
+ scripts
91
96
  });
92
97
  };
@@ -22,8 +22,11 @@ __export(webstudio_component_exports, {
22
22
  collapsedAttribute: () => collapsedAttribute,
23
23
  componentAttribute: () => componentAttribute,
24
24
  idAttribute: () => idAttribute,
25
+ indexAttribute: () => indexAttribute,
25
26
  renderWebstudioComponentChildren: () => renderWebstudioComponentChildren,
26
- showAttribute: () => showAttribute
27
+ selectorIdAttribute: () => selectorIdAttribute,
28
+ showAttribute: () => showAttribute,
29
+ splitPropsWithWebstudioAttributes: () => splitPropsWithWebstudioAttributes
27
30
  });
28
31
  module.exports = __toCommonJS(webstudio_component_exports);
29
32
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -44,13 +47,7 @@ const renderWebstudioComponentChildren = (children) => {
44
47
  return typeof child === "string" ? renderText(child) : child;
45
48
  });
46
49
  };
47
- const WebstudioComponent = ({
48
- instance,
49
- instanceSelector,
50
- children,
51
- components,
52
- ...rest
53
- }) => {
50
+ const WebstudioComponent = (0, import_react.forwardRef)(({ instance, instanceSelector, children, components, ...rest }, ref) => {
54
51
  const { [showAttribute]: show = true, ...instanceProps } = (0, import_props.useInstanceProps)(
55
52
  instance.id
56
53
  );
@@ -67,9 +64,28 @@ const WebstudioComponent = ({
67
64
  if (Component === void 0) {
68
65
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {});
69
66
  }
70
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, children: renderWebstudioComponentChildren(children) });
71
- };
67
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, ref, children: renderWebstudioComponentChildren(children) });
68
+ });
72
69
  const idAttribute = "data-ws-id";
70
+ const selectorIdAttribute = "data-ws-selector";
73
71
  const componentAttribute = "data-ws-component";
74
72
  const showAttribute = "data-ws-show";
73
+ const indexAttribute = "data-ws-index";
75
74
  const collapsedAttribute = "data-ws-collapsed";
75
+ const splitPropsWithWebstudioAttributes = ({
76
+ [idAttribute]: idAttributeValue,
77
+ [componentAttribute]: componentAttributeValue,
78
+ [showAttribute]: showAttributeValue,
79
+ [collapsedAttribute]: collapsedAttributeValue,
80
+ [selectorIdAttribute]: parentIdAttributeValue,
81
+ ...props
82
+ }) => [
83
+ {
84
+ [idAttribute]: idAttributeValue,
85
+ [componentAttribute]: componentAttributeValue,
86
+ [showAttribute]: showAttributeValue,
87
+ [collapsedAttribute]: collapsedAttributeValue,
88
+ [selectorIdAttribute]: parentIdAttributeValue
89
+ },
90
+ props
91
+ ];
@@ -0,0 +1,111 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { getStyleDeclKey } from "@webstudio-is/project-build";
3
+ import { generateDataFromEmbedTemplate } from "./embed-template";
4
+ import { generateCssText } from "./css";
5
+ import { InstanceRoot, WebstudioComponent } from "./tree";
6
+ import {
7
+ decodeVariablesMap,
8
+ encodeDataSourceVariable,
9
+ encodeVariablesMap,
10
+ executeComputingExpressions,
11
+ executeEffectfulExpression
12
+ } from "./expression";
13
+ import { getIndexesWithinAncestors } from "./instance-utils";
14
+ const renderComponentTemplate = ({
15
+ name,
16
+ metas: metasRecord,
17
+ components
18
+ }) => {
19
+ const metas = new Map(Object.entries(metasRecord));
20
+ const data = generateDataFromEmbedTemplate(
21
+ metas.get(name)?.template ?? [
22
+ {
23
+ type: "instance",
24
+ component: name,
25
+ children: []
26
+ }
27
+ ],
28
+ "base"
29
+ );
30
+ const instances = [
31
+ [
32
+ "root",
33
+ {
34
+ type: "instance",
35
+ id: "root",
36
+ component: "Box",
37
+ children: data.children
38
+ }
39
+ ],
40
+ ...data.instances.map(
41
+ (instance) => [instance.id, instance]
42
+ )
43
+ ];
44
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
45
+ /* @__PURE__ */ jsx("style", { children: generateCssText(
46
+ {
47
+ assets: [],
48
+ breakpoints: [["base", { id: "base", label: "base" }]],
49
+ styles: data.styles.map((item) => [getStyleDeclKey(item), item]),
50
+ styleSourceSelections: data.styleSourceSelections.map((item) => [
51
+ item.instanceId,
52
+ item
53
+ ]),
54
+ componentMetas: metas
55
+ },
56
+ { assetBaseUrl: "/" }
57
+ ) }),
58
+ /* @__PURE__ */ jsx(
59
+ InstanceRoot,
60
+ {
61
+ data: {
62
+ page: {
63
+ path: "",
64
+ id: "",
65
+ name: "",
66
+ title: "",
67
+ meta: {},
68
+ rootInstanceId: "root"
69
+ },
70
+ pages: [],
71
+ assets: [],
72
+ build: {
73
+ instances,
74
+ props: data.props.map((prop) => [prop.id, prop]),
75
+ dataSources: data.dataSources.map((dataSource) => [
76
+ dataSource.id,
77
+ dataSource
78
+ ])
79
+ }
80
+ },
81
+ executeComputingExpressions: (values) => {
82
+ const expressions = /* @__PURE__ */ new Map();
83
+ for (const dataSource of data.dataSources) {
84
+ const name2 = encodeDataSourceVariable(dataSource.id);
85
+ if (dataSource.type === "expression") {
86
+ expressions.set(name2, dataSource.code);
87
+ }
88
+ }
89
+ return decodeVariablesMap(
90
+ executeComputingExpressions(expressions, encodeVariablesMap(values))
91
+ );
92
+ },
93
+ executeEffectfulExpression: (code, args, values) => {
94
+ return decodeVariablesMap(
95
+ executeEffectfulExpression(code, args, encodeVariablesMap(values))
96
+ );
97
+ },
98
+ Component: WebstudioComponent,
99
+ components: new Map(Object.entries(components)),
100
+ indexesWithinAncestors: getIndexesWithinAncestors(
101
+ metas,
102
+ new Map(instances),
103
+ ["root"]
104
+ )
105
+ }
106
+ )
107
+ ] });
108
+ };
109
+ export {
110
+ renderComponentTemplate
111
+ };
@@ -11,6 +11,7 @@ const componentCategories = [
11
11
  "text",
12
12
  "media",
13
13
  "forms",
14
+ "radix",
14
15
  "hidden"
15
16
  ];
16
17
  const stateCategories = ["states", "component-states"];
@@ -35,7 +36,16 @@ const WsComponentMeta = z.object({
35
36
  type: z.enum(["container", "control", "embed", "rich-text-child"]),
36
37
  requiredAncestors: z.optional(z.array(z.string())),
37
38
  invalidAncestors: z.optional(z.array(z.string())),
39
+ // when this field is specified component receives
40
+ // prop with index of same components withiin specified ancestor
41
+ // important to automatically enumerate collections without
42
+ // naming every item manually
43
+ indexWithinAncestor: z.optional(z.string()),
38
44
  stylable: z.optional(z.boolean()),
45
+ // specifies whether the instance can be deleted,
46
+ // copied or dragged out of its parent instance
47
+ // true by default
48
+ detachable: z.optional(z.boolean()),
39
49
  label: z.string(),
40
50
  description: z.string().optional(),
41
51
  icon: z.string(),
@@ -0,0 +1 @@
1
+ import { componentAttribute, idAttribute } from "../tree";
package/lib/context.js CHANGED
@@ -15,7 +15,8 @@ const ReactSdkContext = createContext({
15
15
  },
16
16
  setBoundDataSourceValue: () => {
17
17
  throw Error("React SDK setBoundDataSourceValue is not implemented");
18
- }
18
+ },
19
+ indexesWithinAncestors: /* @__PURE__ */ new Map()
19
20
  });
20
21
  export {
21
22
  ReactSdkContext
package/lib/css/index.js CHANGED
@@ -1,4 +1,3 @@
1
- export * from "./get-browser-style";
2
1
  export * from "./global-rules";
3
2
  export * from "./style-rules";
4
3
  export * from "./css";
@@ -49,7 +49,7 @@ const getPresetStyleRules = (component, presetStyle) => {
49
49
  const presetStyleRules = /* @__PURE__ */ new Map();
50
50
  for (const [tag, styles] of Object.entries(presetStyle)) {
51
51
  for (const styleDecl of styles) {
52
- const selector = `${tag}:where([${componentAttribute}=${component}])${styleDecl.state ?? ""}`;
52
+ const selector = `${tag}:where([${componentAttribute}="${component}"])${styleDecl.state ?? ""}`;
53
53
  let rule = presetStyleRules.get(selector);
54
54
  if (rule === void 0) {
55
55
  rule = {};
@@ -1,46 +1,59 @@
1
1
  import { z } from "zod";
2
2
  import { nanoid } from "nanoid";
3
+ import {
4
+ Instance,
5
+ PropsList,
6
+ StyleSourceSelectionsList,
7
+ StyleSourcesList,
8
+ StylesList,
9
+ Breakpoint,
10
+ DataSource
11
+ } from "@webstudio-is/project-build";
3
12
  import { StyleValue } from "@webstudio-is/css-data";
4
13
  import { encodeDataSourceVariable, validateExpression } from "./expression";
5
14
  const EmbedTemplateText = z.object({
6
15
  type: z.literal("text"),
7
16
  value: z.string()
8
17
  });
9
- const DataSourceVariableRef = z.object({
10
- type: z.literal("variable"),
11
- name: z.string()
12
- });
13
- const DataSourceRef = z.union([
14
- DataSourceVariableRef,
18
+ const EmbedTemplateDataSource = z.union([
19
+ z.object({
20
+ type: z.literal("variable"),
21
+ initialValue: z.union([
22
+ z.string(),
23
+ z.number(),
24
+ z.boolean(),
25
+ z.array(z.string())
26
+ ])
27
+ }),
15
28
  z.object({
16
29
  type: z.literal("expression"),
17
- name: z.string(),
18
30
  code: z.string()
19
31
  })
20
32
  ]);
21
33
  const EmbedTemplateProp = z.union([
34
+ z.object({
35
+ type: z.literal("dataSource"),
36
+ name: z.string(),
37
+ dataSourceName: z.string()
38
+ }),
22
39
  z.object({
23
40
  type: z.literal("number"),
24
41
  name: z.string(),
25
- dataSourceRef: z.optional(DataSourceRef),
26
42
  value: z.number()
27
43
  }),
28
44
  z.object({
29
45
  type: z.literal("string"),
30
46
  name: z.string(),
31
- dataSourceRef: z.optional(DataSourceRef),
32
47
  value: z.string()
33
48
  }),
34
49
  z.object({
35
50
  type: z.literal("boolean"),
36
51
  name: z.string(),
37
- dataSourceRef: z.optional(DataSourceRef),
38
52
  value: z.boolean()
39
53
  }),
40
54
  z.object({
41
55
  type: z.literal("string[]"),
42
56
  name: z.string(),
43
- dataSourceRef: z.optional(DataSourceRef),
44
57
  value: z.array(z.string())
45
58
  }),
46
59
  z.object({
@@ -49,6 +62,7 @@ const EmbedTemplateProp = z.union([
49
62
  value: z.array(
50
63
  z.object({
51
64
  type: z.literal("execute"),
65
+ args: z.optional(z.array(z.string())),
52
66
  code: z.string()
53
67
  })
54
68
  )
@@ -66,6 +80,7 @@ const EmbedTemplateInstance = z.lazy(
66
80
  type: z.literal("instance"),
67
81
  component: z.string(),
68
82
  label: z.optional(z.string()),
83
+ dataSources: z.optional(z.record(z.string(), EmbedTemplateDataSource)),
69
84
  props: z.optional(z.array(EmbedTemplateProp)),
70
85
  styles: z.optional(z.array(EmbedTemplateStyleDecl)),
71
86
  children: WsEmbedTemplate
@@ -74,11 +89,58 @@ const EmbedTemplateInstance = z.lazy(
74
89
  const WsEmbedTemplate = z.lazy(
75
90
  () => z.array(z.union([EmbedTemplateInstance, EmbedTemplateText]))
76
91
  );
92
+ const getDataSourceValue = (value) => {
93
+ if (typeof value === "string") {
94
+ return { type: "string", value };
95
+ }
96
+ if (typeof value === "number") {
97
+ return { type: "number", value };
98
+ }
99
+ if (typeof value === "boolean") {
100
+ return { type: "boolean", value };
101
+ }
102
+ if (Array.isArray(value)) {
103
+ return { type: "string[]", value };
104
+ }
105
+ value;
106
+ throw Error("Impossible case");
107
+ };
77
108
  const createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceByRef, styleSourceSelections, styleSources, styles, defaultBreakpointId) => {
78
109
  const parentChildren = [];
79
110
  for (const item of treeTemplate) {
80
111
  if (item.type === "instance") {
81
112
  const instanceId = nanoid();
113
+ if (item.dataSources) {
114
+ for (const [name, dataSource] of Object.entries(item.dataSources)) {
115
+ if (dataSourceByRef.has(name)) {
116
+ throw Error(`${name} data source already defined`);
117
+ }
118
+ if (dataSource.type === "variable") {
119
+ dataSourceByRef.set(name, {
120
+ type: "variable",
121
+ id: nanoid(),
122
+ scopeInstanceId: instanceId,
123
+ name,
124
+ value: getDataSourceValue(dataSource.initialValue)
125
+ });
126
+ }
127
+ if (dataSource.type === "expression") {
128
+ dataSourceByRef.set(name, {
129
+ type: "expression",
130
+ id: nanoid(),
131
+ scopeInstanceId: instanceId,
132
+ name,
133
+ // replace all references with variable names
134
+ code: validateExpression(dataSource.code, {
135
+ transformIdentifier: (ref) => {
136
+ const id = dataSourceByRef.get(ref)?.id ?? ref;
137
+ return encodeDataSourceVariable(id);
138
+ }
139
+ })
140
+ });
141
+ }
142
+ }
143
+ }
82
144
  if (item.props) {
83
145
  for (const prop of item.props) {
84
146
  const propId = nanoid();
@@ -89,12 +151,17 @@ const createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceB
89
151
  type: "action",
90
152
  name: prop.name,
91
153
  value: prop.value.map((value) => {
154
+ const args = value.args ?? [];
92
155
  return {
93
156
  type: "execute",
157
+ args,
94
158
  // replace all references with variable names
95
159
  code: validateExpression(value.code, {
96
160
  effectful: true,
97
161
  transformIdentifier: (ref) => {
162
+ if (args.includes(ref)) {
163
+ return ref;
164
+ }
98
165
  const id = dataSourceByRef.get(ref)?.id ?? ref;
99
166
  return encodeDataSourceVariable(id);
100
167
  }
@@ -104,51 +171,21 @@ const createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceB
104
171
  });
105
172
  continue;
106
173
  }
107
- if (prop.dataSourceRef === void 0) {
108
- props.push({ id: propId, instanceId, ...prop });
109
- continue;
110
- }
111
- let dataSource = dataSourceByRef.get(prop.dataSourceRef.name);
112
- if (dataSource === void 0) {
113
- const id = nanoid();
114
- const { name: propName, dataSourceRef, ...rest } = prop;
115
- if (dataSourceRef.type === "variable") {
116
- dataSource = {
117
- type: "variable",
118
- id,
119
- // the first instance where data source is appeared in becomes its scope
120
- scopeInstanceId: instanceId,
121
- name: dataSourceRef.name,
122
- value: rest
123
- };
124
- dataSourceByRef.set(dataSourceRef.name, dataSource);
125
- } else if (dataSourceRef.type === "expression") {
126
- dataSource = {
127
- type: "expression",
128
- id,
129
- scopeInstanceId: instanceId,
130
- name: dataSourceRef.name,
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
- })
138
- };
139
- dataSourceByRef.set(dataSourceRef.name, dataSource);
140
- } else {
141
- dataSourceRef;
142
- continue;
174
+ if (prop.type === "dataSource") {
175
+ const dataSource = dataSourceByRef.get(prop.dataSourceName);
176
+ if (dataSource === void 0) {
177
+ throw Error(`${prop.dataSourceName} data source is not defined`);
143
178
  }
179
+ props.push({
180
+ id: propId,
181
+ instanceId,
182
+ type: "dataSource",
183
+ name: prop.name,
184
+ value: dataSource.id
185
+ });
186
+ continue;
144
187
  }
145
- props.push({
146
- id: propId,
147
- instanceId,
148
- type: "dataSource",
149
- name: prop.name,
150
- value: dataSource.id
151
- });
188
+ props.push({ id: propId, instanceId, ...prop });
152
189
  }
153
190
  }
154
191
  if (item.styles) {
@@ -230,9 +267,55 @@ const generateDataFromEmbedTemplate = (treeTemplate, defaultBreakpointId) => {
230
267
  styles
231
268
  };
232
269
  };
270
+ const namespaceEmbedTemplateComponents = (template, namespace, components) => {
271
+ return template.map((item) => {
272
+ if (item.type === "text") {
273
+ return item;
274
+ }
275
+ if (item.type === "instance") {
276
+ const prefix = components.has(item.component) ? `${namespace}:` : "";
277
+ return {
278
+ ...item,
279
+ component: `${prefix}${item.component}`,
280
+ children: namespaceEmbedTemplateComponents(
281
+ item.children,
282
+ namespace,
283
+ components
284
+ )
285
+ };
286
+ }
287
+ item;
288
+ throw Error("Impossible case");
289
+ });
290
+ };
291
+ const namespaceMeta = (meta, namespace, components) => {
292
+ const newMeta = { ...meta };
293
+ if (newMeta.requiredAncestors) {
294
+ newMeta.requiredAncestors = newMeta.requiredAncestors.map(
295
+ (component) => components.has(component) ? `${namespace}:${component}` : component
296
+ );
297
+ }
298
+ if (newMeta.invalidAncestors) {
299
+ newMeta.invalidAncestors = newMeta.invalidAncestors.map(
300
+ (component) => components.has(component) ? `${namespace}:${component}` : component
301
+ );
302
+ }
303
+ if (newMeta.indexWithinAncestor) {
304
+ newMeta.indexWithinAncestor = components.has(newMeta.indexWithinAncestor) ? `${namespace}:${newMeta.indexWithinAncestor}` : newMeta.indexWithinAncestor;
305
+ }
306
+ if (newMeta.template) {
307
+ newMeta.template = namespaceEmbedTemplateComponents(
308
+ newMeta.template,
309
+ namespace,
310
+ components
311
+ );
312
+ }
313
+ return newMeta;
314
+ };
233
315
  export {
234
316
  EmbedTemplateInstance,
235
317
  EmbedTemplateStyleDecl,
236
318
  WsEmbedTemplate,
237
- generateDataFromEmbedTemplate
319
+ generateDataFromEmbedTemplate,
320
+ namespaceMeta
238
321
  };