@webstudio-is/react-sdk 0.83.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 (54) hide show
  1. package/lib/cjs/component-renderer.js +125 -0
  2. package/lib/cjs/components/component-meta.js +5 -0
  3. package/lib/cjs/context.js +2 -1
  4. package/lib/cjs/css/style-rules.js +1 -1
  5. package/lib/cjs/embed-template.js +101 -55
  6. package/lib/cjs/hook.js +34 -0
  7. package/lib/cjs/index.js +6 -0
  8. package/lib/cjs/instance-utils.js +65 -0
  9. package/lib/cjs/props.js +12 -2
  10. package/lib/cjs/tree/create-elements-tree.js +5 -4
  11. package/lib/cjs/tree/root.js +6 -2
  12. package/lib/cjs/tree/webstudio-component.js +2 -0
  13. package/lib/component-renderer.js +111 -0
  14. package/lib/components/component-meta.js +5 -0
  15. package/lib/context.js +2 -1
  16. package/lib/css/style-rules.js +1 -1
  17. package/lib/embed-template.js +101 -55
  18. package/lib/hook.js +14 -0
  19. package/lib/index.js +8 -1
  20. package/lib/instance-utils.js +45 -0
  21. package/lib/props.js +13 -3
  22. package/lib/tree/create-elements-tree.js +5 -4
  23. package/lib/tree/root.js +6 -2
  24. package/lib/tree/webstudio-component.js +2 -0
  25. package/lib/types/component-renderer.d.ts +8 -0
  26. package/lib/types/components/component-meta.d.ts +9 -6
  27. package/lib/types/context.d.ts +2 -0
  28. package/lib/types/css/css.d.ts +19 -19
  29. package/lib/types/css/global-rules.d.ts +19 -19
  30. package/lib/types/css/normalize.d.ts +47 -47
  31. package/lib/types/embed-template.d.ts +291 -181
  32. package/lib/types/hook.d.ts +31 -0
  33. package/lib/types/index.d.ts +4 -1
  34. package/lib/types/instance-utils.d.ts +16 -0
  35. package/lib/types/instance-utils.test.d.ts +1 -0
  36. package/lib/types/props.d.ts +47 -46
  37. package/lib/types/tree/create-elements-tree.d.ts +5 -2
  38. package/lib/types/tree/root.d.ts +5 -2
  39. package/lib/types/tree/webstudio-component.d.ts +1 -0
  40. package/package.json +11 -11
  41. package/src/component-renderer.tsx +117 -0
  42. package/src/components/component-meta.ts +5 -0
  43. package/src/context.tsx +3 -0
  44. package/src/css/style-rules.ts +1 -1
  45. package/src/embed-template.test.ts +81 -70
  46. package/src/embed-template.ts +116 -56
  47. package/src/hook.ts +42 -0
  48. package/src/index.ts +4 -0
  49. package/src/instance-utils.test.ts +89 -0
  50. package/src/instance-utils.ts +65 -0
  51. package/src/props.ts +13 -1
  52. package/src/tree/create-elements-tree.tsx +8 -3
  53. package/src/tree/root.ts +8 -0
  54. package/src/tree/webstudio-component.tsx +1 -0
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var component_renderer_exports = {};
20
+ __export(component_renderer_exports, {
21
+ renderComponentTemplate: () => renderComponentTemplate
22
+ });
23
+ module.exports = __toCommonJS(component_renderer_exports);
24
+ var import_jsx_runtime = require("react/jsx-runtime");
25
+ var import_project_build = require("@webstudio-is/project-build");
26
+ var import_embed_template = require("./embed-template");
27
+ var import_css = require("./css");
28
+ var import_tree = require("./tree");
29
+ var import_expression = require("./expression");
30
+ var import_instance_utils = require("./instance-utils");
31
+ const renderComponentTemplate = ({
32
+ name,
33
+ metas: metasRecord,
34
+ components
35
+ }) => {
36
+ const metas = new Map(Object.entries(metasRecord));
37
+ const data = (0, import_embed_template.generateDataFromEmbedTemplate)(
38
+ metas.get(name)?.template ?? [
39
+ {
40
+ type: "instance",
41
+ component: name,
42
+ children: []
43
+ }
44
+ ],
45
+ "base"
46
+ );
47
+ const instances = [
48
+ [
49
+ "root",
50
+ {
51
+ type: "instance",
52
+ id: "root",
53
+ component: "Box",
54
+ children: data.children
55
+ }
56
+ ],
57
+ ...data.instances.map(
58
+ (instance) => [instance.id, instance]
59
+ )
60
+ ];
61
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
62
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: (0, import_css.generateCssText)(
63
+ {
64
+ assets: [],
65
+ breakpoints: [["base", { id: "base", label: "base" }]],
66
+ styles: data.styles.map((item) => [(0, import_project_build.getStyleDeclKey)(item), item]),
67
+ styleSourceSelections: data.styleSourceSelections.map((item) => [
68
+ item.instanceId,
69
+ item
70
+ ]),
71
+ componentMetas: metas
72
+ },
73
+ { assetBaseUrl: "/" }
74
+ ) }),
75
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
76
+ import_tree.InstanceRoot,
77
+ {
78
+ data: {
79
+ page: {
80
+ path: "",
81
+ id: "",
82
+ name: "",
83
+ title: "",
84
+ meta: {},
85
+ rootInstanceId: "root"
86
+ },
87
+ pages: [],
88
+ assets: [],
89
+ build: {
90
+ instances,
91
+ props: data.props.map((prop) => [prop.id, prop]),
92
+ dataSources: data.dataSources.map((dataSource) => [
93
+ dataSource.id,
94
+ dataSource
95
+ ])
96
+ }
97
+ },
98
+ executeComputingExpressions: (values) => {
99
+ const expressions = /* @__PURE__ */ new Map();
100
+ for (const dataSource of data.dataSources) {
101
+ const name2 = (0, import_expression.encodeDataSourceVariable)(dataSource.id);
102
+ if (dataSource.type === "expression") {
103
+ expressions.set(name2, dataSource.code);
104
+ }
105
+ }
106
+ return (0, import_expression.decodeVariablesMap)(
107
+ (0, import_expression.executeComputingExpressions)(expressions, (0, import_expression.encodeVariablesMap)(values))
108
+ );
109
+ },
110
+ executeEffectfulExpression: (code, args, values) => {
111
+ return (0, import_expression.decodeVariablesMap)(
112
+ (0, import_expression.executeEffectfulExpression)(code, args, (0, import_expression.encodeVariablesMap)(values))
113
+ );
114
+ },
115
+ Component: import_tree.WebstudioComponent,
116
+ components: new Map(Object.entries(components)),
117
+ indexesWithinAncestors: (0, import_instance_utils.getIndexesWithinAncestors)(
118
+ metas,
119
+ new Map(instances),
120
+ ["root"]
121
+ )
122
+ }
123
+ )
124
+ ] });
125
+ };
@@ -62,6 +62,11 @@ const WsComponentMeta = import_zod.z.object({
62
62
  type: import_zod.z.enum(["container", "control", "embed", "rich-text-child"]),
63
63
  requiredAncestors: import_zod.z.optional(import_zod.z.array(import_zod.z.string())),
64
64
  invalidAncestors: import_zod.z.optional(import_zod.z.array(import_zod.z.string())),
65
+ // when this field is specified component receives
66
+ // prop with index of same components withiin specified ancestor
67
+ // important to automatically enumerate collections without
68
+ // naming every item manually
69
+ indexWithinAncestor: import_zod.z.optional(import_zod.z.string()),
65
70
  stylable: import_zod.z.optional(import_zod.z.boolean()),
66
71
  // specifies whether the instance can be deleted,
67
72
  // copied or dragged out of its parent instance
@@ -38,5 +38,6 @@ const ReactSdkContext = (0, import_react.createContext)({
38
38
  },
39
39
  setBoundDataSourceValue: () => {
40
40
  throw Error("React SDK setBoundDataSourceValue is not implemented");
41
- }
41
+ },
42
+ indexesWithinAncestors: /* @__PURE__ */ new Map()
42
43
  });
@@ -73,7 +73,7 @@ const getPresetStyleRules = (component, presetStyle) => {
73
73
  const presetStyleRules = /* @__PURE__ */ new Map();
74
74
  for (const [tag, styles] of Object.entries(presetStyle)) {
75
75
  for (const styleDecl of styles) {
76
- const selector = `${tag}:where([${import_tree.componentAttribute}=${component}])${styleDecl.state ?? ""}`;
76
+ const selector = `${tag}:where([${import_tree.componentAttribute}="${component}"])${styleDecl.state ?? ""}`;
77
77
  let rule = presetStyleRules.get(selector);
78
78
  if (rule === void 0) {
79
79
  rule = {};
@@ -22,7 +22,7 @@ __export(embed_template_exports, {
22
22
  EmbedTemplateStyleDecl: () => EmbedTemplateStyleDecl,
23
23
  WsEmbedTemplate: () => WsEmbedTemplate,
24
24
  generateDataFromEmbedTemplate: () => generateDataFromEmbedTemplate,
25
- namespaceEmbedTemplateComponents: () => namespaceEmbedTemplateComponents
25
+ namespaceMeta: () => namespaceMeta
26
26
  });
27
27
  module.exports = __toCommonJS(embed_template_exports);
28
28
  var import_zod = require("zod");
@@ -34,41 +34,45 @@ const EmbedTemplateText = import_zod.z.object({
34
34
  type: import_zod.z.literal("text"),
35
35
  value: import_zod.z.string()
36
36
  });
37
- const DataSourceVariableRef = import_zod.z.object({
38
- type: import_zod.z.literal("variable"),
39
- name: import_zod.z.string()
40
- });
41
- const DataSourceRef = import_zod.z.union([
42
- DataSourceVariableRef,
37
+ const EmbedTemplateDataSource = import_zod.z.union([
38
+ import_zod.z.object({
39
+ type: import_zod.z.literal("variable"),
40
+ initialValue: import_zod.z.union([
41
+ import_zod.z.string(),
42
+ import_zod.z.number(),
43
+ import_zod.z.boolean(),
44
+ import_zod.z.array(import_zod.z.string())
45
+ ])
46
+ }),
43
47
  import_zod.z.object({
44
48
  type: import_zod.z.literal("expression"),
45
- name: import_zod.z.string(),
46
49
  code: import_zod.z.string()
47
50
  })
48
51
  ]);
49
52
  const EmbedTemplateProp = import_zod.z.union([
53
+ import_zod.z.object({
54
+ type: import_zod.z.literal("dataSource"),
55
+ name: import_zod.z.string(),
56
+ dataSourceName: import_zod.z.string()
57
+ }),
50
58
  import_zod.z.object({
51
59
  type: import_zod.z.literal("number"),
52
60
  name: import_zod.z.string(),
53
- dataSourceRef: import_zod.z.optional(DataSourceRef),
54
61
  value: import_zod.z.number()
55
62
  }),
56
63
  import_zod.z.object({
57
64
  type: import_zod.z.literal("string"),
58
65
  name: import_zod.z.string(),
59
- dataSourceRef: import_zod.z.optional(DataSourceRef),
60
66
  value: import_zod.z.string()
61
67
  }),
62
68
  import_zod.z.object({
63
69
  type: import_zod.z.literal("boolean"),
64
70
  name: import_zod.z.string(),
65
- dataSourceRef: import_zod.z.optional(DataSourceRef),
66
71
  value: import_zod.z.boolean()
67
72
  }),
68
73
  import_zod.z.object({
69
74
  type: import_zod.z.literal("string[]"),
70
75
  name: import_zod.z.string(),
71
- dataSourceRef: import_zod.z.optional(DataSourceRef),
72
76
  value: import_zod.z.array(import_zod.z.string())
73
77
  }),
74
78
  import_zod.z.object({
@@ -95,6 +99,7 @@ const EmbedTemplateInstance = import_zod.z.lazy(
95
99
  type: import_zod.z.literal("instance"),
96
100
  component: import_zod.z.string(),
97
101
  label: import_zod.z.optional(import_zod.z.string()),
102
+ dataSources: import_zod.z.optional(import_zod.z.record(import_zod.z.string(), EmbedTemplateDataSource)),
98
103
  props: import_zod.z.optional(import_zod.z.array(EmbedTemplateProp)),
99
104
  styles: import_zod.z.optional(import_zod.z.array(EmbedTemplateStyleDecl)),
100
105
  children: WsEmbedTemplate
@@ -103,11 +108,58 @@ const EmbedTemplateInstance = import_zod.z.lazy(
103
108
  const WsEmbedTemplate = import_zod.z.lazy(
104
109
  () => import_zod.z.array(import_zod.z.union([EmbedTemplateInstance, EmbedTemplateText]))
105
110
  );
111
+ const getDataSourceValue = (value) => {
112
+ if (typeof value === "string") {
113
+ return { type: "string", value };
114
+ }
115
+ if (typeof value === "number") {
116
+ return { type: "number", value };
117
+ }
118
+ if (typeof value === "boolean") {
119
+ return { type: "boolean", value };
120
+ }
121
+ if (Array.isArray(value)) {
122
+ return { type: "string[]", value };
123
+ }
124
+ value;
125
+ throw Error("Impossible case");
126
+ };
106
127
  const createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceByRef, styleSourceSelections, styleSources, styles, defaultBreakpointId) => {
107
128
  const parentChildren = [];
108
129
  for (const item of treeTemplate) {
109
130
  if (item.type === "instance") {
110
131
  const instanceId = (0, import_nanoid.nanoid)();
132
+ if (item.dataSources) {
133
+ for (const [name, dataSource] of Object.entries(item.dataSources)) {
134
+ if (dataSourceByRef.has(name)) {
135
+ throw Error(`${name} data source already defined`);
136
+ }
137
+ if (dataSource.type === "variable") {
138
+ dataSourceByRef.set(name, {
139
+ type: "variable",
140
+ id: (0, import_nanoid.nanoid)(),
141
+ scopeInstanceId: instanceId,
142
+ name,
143
+ value: getDataSourceValue(dataSource.initialValue)
144
+ });
145
+ }
146
+ if (dataSource.type === "expression") {
147
+ dataSourceByRef.set(name, {
148
+ type: "expression",
149
+ id: (0, import_nanoid.nanoid)(),
150
+ scopeInstanceId: instanceId,
151
+ name,
152
+ // replace all references with variable names
153
+ code: (0, import_expression.validateExpression)(dataSource.code, {
154
+ transformIdentifier: (ref) => {
155
+ const id = dataSourceByRef.get(ref)?.id ?? ref;
156
+ return (0, import_expression.encodeDataSourceVariable)(id);
157
+ }
158
+ })
159
+ });
160
+ }
161
+ }
162
+ }
111
163
  if (item.props) {
112
164
  for (const prop of item.props) {
113
165
  const propId = (0, import_nanoid.nanoid)();
@@ -138,51 +190,21 @@ const createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceB
138
190
  });
139
191
  continue;
140
192
  }
141
- if (prop.dataSourceRef === void 0) {
142
- props.push({ id: propId, instanceId, ...prop });
143
- continue;
144
- }
145
- let dataSource = dataSourceByRef.get(prop.dataSourceRef.name);
146
- if (dataSource === void 0) {
147
- const id = (0, import_nanoid.nanoid)();
148
- const { name: propName, dataSourceRef, ...rest } = prop;
149
- if (dataSourceRef.type === "variable") {
150
- dataSource = {
151
- type: "variable",
152
- id,
153
- // the first instance where data source is appeared in becomes its scope
154
- scopeInstanceId: instanceId,
155
- name: dataSourceRef.name,
156
- value: rest
157
- };
158
- dataSourceByRef.set(dataSourceRef.name, dataSource);
159
- } else if (dataSourceRef.type === "expression") {
160
- dataSource = {
161
- type: "expression",
162
- id,
163
- scopeInstanceId: instanceId,
164
- name: dataSourceRef.name,
165
- // replace all references with variable names
166
- code: (0, import_expression.validateExpression)(dataSourceRef.code, {
167
- transformIdentifier: (ref) => {
168
- const id2 = dataSourceByRef.get(ref)?.id ?? ref;
169
- return (0, import_expression.encodeDataSourceVariable)(id2);
170
- }
171
- })
172
- };
173
- dataSourceByRef.set(dataSourceRef.name, dataSource);
174
- } else {
175
- dataSourceRef;
176
- continue;
193
+ if (prop.type === "dataSource") {
194
+ const dataSource = dataSourceByRef.get(prop.dataSourceName);
195
+ if (dataSource === void 0) {
196
+ throw Error(`${prop.dataSourceName} data source is not defined`);
177
197
  }
198
+ props.push({
199
+ id: propId,
200
+ instanceId,
201
+ type: "dataSource",
202
+ name: prop.name,
203
+ value: dataSource.id
204
+ });
205
+ continue;
178
206
  }
179
- props.push({
180
- id: propId,
181
- instanceId,
182
- type: "dataSource",
183
- name: prop.name,
184
- value: dataSource.id
185
- });
207
+ props.push({ id: propId, instanceId, ...prop });
186
208
  }
187
209
  }
188
210
  if (item.styles) {
@@ -285,3 +307,27 @@ const namespaceEmbedTemplateComponents = (template, namespace, components) => {
285
307
  throw Error("Impossible case");
286
308
  });
287
309
  };
310
+ const namespaceMeta = (meta, namespace, components) => {
311
+ const newMeta = { ...meta };
312
+ if (newMeta.requiredAncestors) {
313
+ newMeta.requiredAncestors = newMeta.requiredAncestors.map(
314
+ (component) => components.has(component) ? `${namespace}:${component}` : component
315
+ );
316
+ }
317
+ if (newMeta.invalidAncestors) {
318
+ newMeta.invalidAncestors = newMeta.invalidAncestors.map(
319
+ (component) => components.has(component) ? `${namespace}:${component}` : component
320
+ );
321
+ }
322
+ if (newMeta.indexWithinAncestor) {
323
+ newMeta.indexWithinAncestor = components.has(newMeta.indexWithinAncestor) ? `${namespace}:${newMeta.indexWithinAncestor}` : newMeta.indexWithinAncestor;
324
+ }
325
+ if (newMeta.template) {
326
+ newMeta.template = namespaceEmbedTemplateComponents(
327
+ newMeta.template,
328
+ namespace,
329
+ components
330
+ );
331
+ }
332
+ return newMeta;
333
+ };
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var hook_exports = {};
20
+ __export(hook_exports, {
21
+ getClosestInstance: () => getClosestInstance
22
+ });
23
+ module.exports = __toCommonJS(hook_exports);
24
+ const getClosestInstance = (instanceSelection, currentInstance, closestComponent) => {
25
+ let matched = false;
26
+ for (const instance of instanceSelection) {
27
+ if (currentInstance === instance) {
28
+ matched = true;
29
+ }
30
+ if (matched && instance.component === closestComponent) {
31
+ return instance;
32
+ }
33
+ }
34
+ };
package/lib/cjs/index.js CHANGED
@@ -31,7 +31,10 @@ __export(src_exports, {
31
31
  executeEffectfulExpression: () => import_expression.executeEffectfulExpression,
32
32
  generateComputingExpressions: () => import_expression.generateComputingExpressions,
33
33
  generateEffectfulExpression: () => import_expression.generateEffectfulExpression,
34
+ getIndexWithinAncestorFromComponentProps: () => import_props.getIndexWithinAncestorFromComponentProps,
35
+ getIndexesWithinAncestors: () => import_instance_utils.getIndexesWithinAncestors,
34
36
  getInstanceIdFromComponentProps: () => import_props.getInstanceIdFromComponentProps,
37
+ renderComponentTemplate: () => import_component_renderer.renderComponentTemplate,
35
38
  stateCategories: () => import_component_meta.stateCategories,
36
39
  useInstanceProps: () => import_props.useInstanceProps,
37
40
  usePropAsset: () => import_props.usePropAsset,
@@ -49,3 +52,6 @@ __reExport(src_exports, require("./embed-template"), module.exports);
49
52
  var import_props = require("./props");
50
53
  var import_context = require("./context");
51
54
  var import_expression = require("./expression");
55
+ var import_component_renderer = require("./component-renderer");
56
+ var import_instance_utils = require("./instance-utils");
57
+ __reExport(src_exports, require("./hook"), module.exports);
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var instance_utils_exports = {};
20
+ __export(instance_utils_exports, {
21
+ getIndexesWithinAncestors: () => getIndexesWithinAncestors
22
+ });
23
+ module.exports = __toCommonJS(instance_utils_exports);
24
+ const getIndexesWithinAncestors = (metas, instances, rootIds) => {
25
+ const ancestors = /* @__PURE__ */ new Set();
26
+ for (const meta of metas.values()) {
27
+ if (meta.indexWithinAncestor !== void 0) {
28
+ ancestors.add(meta.indexWithinAncestor);
29
+ }
30
+ }
31
+ const indexes = /* @__PURE__ */ new Map();
32
+ const traverseInstances = (instances2, instanceId, latestIndexes2 = /* @__PURE__ */ new Map()) => {
33
+ const instance = instances2.get(instanceId);
34
+ if (instance === void 0) {
35
+ return;
36
+ }
37
+ const meta = metas.get(instance.component);
38
+ if (meta === void 0) {
39
+ return;
40
+ }
41
+ if (ancestors.has(instance.component)) {
42
+ latestIndexes2 = new Map(latestIndexes2);
43
+ latestIndexes2.set(instance.component, /* @__PURE__ */ new Map());
44
+ }
45
+ if (meta.indexWithinAncestor !== void 0) {
46
+ const ancestorIndexes = latestIndexes2.get(meta.indexWithinAncestor);
47
+ if (ancestorIndexes !== void 0) {
48
+ let index = ancestorIndexes.get(instance.component) ?? -1;
49
+ index += 1;
50
+ ancestorIndexes.set(instance.component, index);
51
+ indexes.set(instance.id, index);
52
+ }
53
+ }
54
+ for (const child of instance.children) {
55
+ if (child.type === "id") {
56
+ traverseInstances(instances2, child.value, latestIndexes2);
57
+ }
58
+ }
59
+ };
60
+ const latestIndexes = /* @__PURE__ */ new Map();
61
+ for (const instanceId of rootIds) {
62
+ traverseInstances(instances, instanceId, latestIndexes);
63
+ }
64
+ return indexes;
65
+ };
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;
@@ -105,7 +111,8 @@ const useInstanceProps = (instanceId) => {
105
111
  instanceId,
106
112
  renderer,
107
113
  executeEffectfulExpression,
108
- setDataSourceValues
114
+ setDataSourceValues,
115
+ index
109
116
  ]);
110
117
  const instancePropsObject = (0, import_react2.useStore)(instancePropsObjectStore);
111
118
  return instancePropsObject;
@@ -192,3 +199,6 @@ const usePropUrl = (instanceId, name) => {
192
199
  const getInstanceIdFromComponentProps = (props) => {
193
200
  return props[import_webstudio_component.idAttribute];
194
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) => {
@@ -29,10 +29,12 @@ var import_webstudio_component = require("./webstudio-component");
29
29
  var import_props = require("../props");
30
30
  const InstanceRoot = ({
31
31
  data,
32
+ indexesWithinAncestors,
32
33
  executeComputingExpressions,
33
34
  executeEffectfulExpression,
34
35
  Component,
35
- components
36
+ components,
37
+ scripts
36
38
  }) => {
37
39
  const dataSourceVariablesStoreRef = (0, import_react.useRef)(void 0);
38
40
  if (dataSourceVariablesStoreRef.current === void 0) {
@@ -84,10 +86,12 @@ const InstanceRoot = ({
84
86
  ),
85
87
  assetsStore: (0, import_nanostores.atom)(new Map(data.assets.map((asset) => [asset.id, asset]))),
86
88
  pagesStore: (0, import_nanostores.atom)(new Map(data.pages.map((page) => [page.id, page]))),
89
+ indexesWithinAncestors,
87
90
  executeEffectfulExpression,
88
91
  dataSourceValuesStore,
89
92
  onDataSourceUpdate,
90
93
  Component: Component ?? import_webstudio_component.WebstudioComponent,
91
- components
94
+ components,
95
+ scripts
92
96
  });
93
97
  };
@@ -22,6 +22,7 @@ __export(webstudio_component_exports, {
22
22
  collapsedAttribute: () => collapsedAttribute,
23
23
  componentAttribute: () => componentAttribute,
24
24
  idAttribute: () => idAttribute,
25
+ indexAttribute: () => indexAttribute,
25
26
  renderWebstudioComponentChildren: () => renderWebstudioComponentChildren,
26
27
  selectorIdAttribute: () => selectorIdAttribute,
27
28
  showAttribute: () => showAttribute,
@@ -69,6 +70,7 @@ const idAttribute = "data-ws-id";
69
70
  const selectorIdAttribute = "data-ws-selector";
70
71
  const componentAttribute = "data-ws-component";
71
72
  const showAttribute = "data-ws-show";
73
+ const indexAttribute = "data-ws-index";
72
74
  const collapsedAttribute = "data-ws-collapsed";
73
75
  const splitPropsWithWebstudioAttributes = ({
74
76
  [idAttribute]: idAttributeValue,