@webstudio-is/react-sdk 0.95.0 → 0.97.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 (44) hide show
  1. package/lib/css/normalize.js +127 -53
  2. package/lib/index.js +1850 -32
  3. package/lib/types/component-renderer.d.ts +3 -1
  4. package/lib/types/context.d.ts +2 -0
  5. package/lib/types/index.d.ts +0 -1
  6. package/lib/types/tree/create-elements-tree.d.ts +3 -1
  7. package/lib/types/tree/root.d.ts +3 -1
  8. package/package.json +7 -7
  9. package/lib/app/index.js +0 -2
  10. package/lib/app/root.js +0 -18
  11. package/lib/component-renderer.js +0 -130
  12. package/lib/components/component-meta.js +0 -62
  13. package/lib/components/components-utils.js +0 -2
  14. package/lib/context.js +0 -21
  15. package/lib/css/css.js +0 -59
  16. package/lib/css/global-rules.js +0 -15
  17. package/lib/css/index.js +0 -4
  18. package/lib/css/normalize-type-check.js +0 -4
  19. package/lib/css/presets.js +0 -25
  20. package/lib/css/style-rules.js +0 -63
  21. package/lib/css/style-rules.test.js +0 -149
  22. package/lib/embed-template.js +0 -341
  23. package/lib/embed-template.test.js +0 -648
  24. package/lib/expression.js +0 -330
  25. package/lib/expression.test.js +0 -281
  26. package/lib/generator.js +0 -112
  27. package/lib/generator.test.js +0 -166
  28. package/lib/hook.js +0 -12
  29. package/lib/hook.test.js +0 -15
  30. package/lib/instance-utils.js +0 -43
  31. package/lib/instance-utils.test.js +0 -65
  32. package/lib/prop-meta.js +0 -150
  33. package/lib/props.js +0 -176
  34. package/lib/props.test.js +0 -159
  35. package/lib/pubsub/create.js +0 -56
  36. package/lib/pubsub/index.js +0 -2
  37. package/lib/pubsub/raf-queue.js +0 -20
  38. package/lib/tree/create-elements-tree.js +0 -134
  39. package/lib/tree/index.js +0 -4
  40. package/lib/tree/root.js +0 -85
  41. package/lib/tree/webstudio-component.js +0 -61
  42. package/lib/types/pubsub/create.d.ts +0 -28
  43. package/lib/types/pubsub/index.d.ts +0 -1
  44. package/lib/types/pubsub/raf-queue.d.ts +0 -1
package/lib/generator.js DELETED
@@ -1,112 +0,0 @@
1
- "use strict";
2
- import {
3
- getIndexesWithinAncestors
4
- } from "./instance-utils";
5
- import {
6
- encodeDataSourceVariable,
7
- generateComputingExpressions,
8
- generateEffectfulExpression
9
- } from "./expression";
10
- export const generateUtilsExport = (siteData) => {
11
- const indexesWithinAncestors = getIndexesWithinAncestors(
12
- siteData.metas,
13
- siteData.instances,
14
- [siteData.page.rootInstanceId]
15
- );
16
- let indexesWithinAncestorsEntries = "";
17
- for (const [key, value] of indexesWithinAncestors) {
18
- const keyString = JSON.stringify(key);
19
- const valueString = JSON.stringify(value);
20
- indexesWithinAncestorsEntries += `[${keyString}, ${valueString}],
21
- `;
22
- }
23
- const generatedIndexesWithinAncestors = `
24
- const indexesWithinAncestors = new Map<string, number>([
25
- ${indexesWithinAncestorsEntries}
26
- ]);
27
- `;
28
- const variables = /* @__PURE__ */ new Set();
29
- const expressions = /* @__PURE__ */ new Map();
30
- for (const dataSource of siteData.dataSources.values()) {
31
- if (dataSource.type === "variable") {
32
- variables.add(encodeDataSourceVariable(dataSource.id));
33
- }
34
- if (dataSource.type === "expression") {
35
- expressions.set(encodeDataSourceVariable(dataSource.id), dataSource.code);
36
- }
37
- }
38
- const generatedExecuteComputingExpressions = `
39
- const rawExecuteComputingExpressions = (
40
- _variables: Map<string, unknown>
41
- ): Map<string, unknown> => {
42
- ${generateComputingExpressions(expressions, variables)}
43
- };
44
- const executeComputingExpressions = (variables: Map<string, unknown>) => {
45
- const encodedvariables = sdk.encodeVariablesMap(variables);
46
- const encodedResult = rawExecuteComputingExpressions(encodedvariables);
47
- return sdk.decodeVariablesMap(encodedResult);
48
- };
49
- `;
50
- let effectfulExpressionsEntries = "";
51
- for (const prop of siteData.props.values()) {
52
- if (prop.type === "action") {
53
- for (const executableValue of prop.value) {
54
- const codeString = JSON.stringify(executableValue.code);
55
- const generatedCode = generateEffectfulExpression(
56
- executableValue.code,
57
- new Set(executableValue.args),
58
- variables
59
- );
60
- const generatedFunction = `(_args: Map<string, any>, _variables: Map<string, any>) => { ${generatedCode} }`;
61
- effectfulExpressionsEntries += `[${codeString}, ${generatedFunction}],
62
- `;
63
- }
64
- }
65
- }
66
- const generatedExecuteEffectfulExpression = `const generatedEffectfulExpressions = new Map<
67
- string,
68
- (args: Map<string, any>, variables: Map<string, any>) => Map<string, unknown>
69
- >([
70
- ${effectfulExpressionsEntries}
71
- ]);
72
-
73
- const rawExecuteEffectfulExpression = (
74
- code: string,
75
- args: Map<string, unknown>,
76
- variables: Map<string, unknown>
77
- ): Map<string, unknown> => {
78
- if(generatedEffectfulExpressions.has(code)) {
79
- return generatedEffectfulExpressions.get(code)!(args, variables);
80
- }
81
- console.error("Effectful expression not found", code);
82
- throw new Error("Effectful expression not found");
83
- };
84
-
85
- const executeEffectfulExpression = (
86
- code: string,
87
- args: Map<string, unknown>,
88
- variables: Map<string, unknown>
89
- ) => {
90
- const encodedvariables = sdk.encodeVariablesMap(variables);
91
- const encodedResult = rawExecuteEffectfulExpression(code, args, encodedvariables);
92
- return sdk.decodeVariablesMap(encodedResult);
93
- };
94
- `;
95
- return `
96
- /* eslint-disable */
97
-
98
- ${generatedIndexesWithinAncestors.trim()}
99
-
100
- ${generatedExecuteComputingExpressions.trim()}
101
-
102
- ${generatedExecuteEffectfulExpression.trim()}
103
-
104
- export const utils = {
105
- indexesWithinAncestors,
106
- executeComputingExpressions,
107
- executeEffectfulExpression,
108
- };
109
-
110
- /* eslint-enable */
111
- `;
112
- };
@@ -1,166 +0,0 @@
1
- "use strict";
2
- import { expect, test } from "@jest/globals";
3
- import { generateUtilsExport } from "./generator";
4
- test("generates utils", () => {
5
- expect(
6
- generateUtilsExport({
7
- page: {
8
- id: "",
9
- path: "",
10
- name: "",
11
- title: "",
12
- meta: {},
13
- rootInstanceId: "tabs"
14
- },
15
- metas: /* @__PURE__ */ new Map([
16
- ["Tabs", { type: "container", label: "", icon: "" }],
17
- [
18
- "TabsContent",
19
- {
20
- type: "container",
21
- label: "",
22
- icon: "",
23
- indexWithinAncestor: "Tabs"
24
- }
25
- ]
26
- ]),
27
- instances: /* @__PURE__ */ new Map([
28
- [
29
- "tabs",
30
- {
31
- id: "tabs",
32
- type: "instance",
33
- component: "Tabs",
34
- children: [
35
- { type: "id", value: "content1" },
36
- { type: "id", value: "content2" }
37
- ]
38
- }
39
- ],
40
- [
41
- "content1",
42
- {
43
- id: "content1",
44
- type: "instance",
45
- component: "TabsContent",
46
- children: []
47
- }
48
- ],
49
- [
50
- "content2",
51
- {
52
- id: "content2",
53
- type: "instance",
54
- component: "TabsContent",
55
- children: []
56
- }
57
- ]
58
- ]),
59
- props: /* @__PURE__ */ new Map([
60
- [
61
- "open",
62
- {
63
- type: "dataSource",
64
- id: "open",
65
- instanceId: "tabs",
66
- name: "open",
67
- value: "tabsOpen"
68
- }
69
- ],
70
- [
71
- "onOpenChange",
72
- {
73
- type: "action",
74
- id: "onOpenChange",
75
- instanceId: "tabs",
76
- name: "onOpenChange",
77
- value: [
78
- {
79
- type: "execute",
80
- args: ["open"],
81
- code: `$ws$dataSource$tabsOpen = open`
82
- }
83
- ]
84
- }
85
- ]
86
- ]),
87
- dataSources: /* @__PURE__ */ new Map([
88
- [
89
- "tabsOpen",
90
- {
91
- id: "tabsOpen",
92
- name: "tabsOpen",
93
- scopeInstanceId: "tabs",
94
- type: "variable",
95
- value: { type: "string", value: "0" }
96
- }
97
- ]
98
- ])
99
- })
100
- ).toMatchInlineSnapshot(`
101
- "
102
- /* eslint-disable */
103
-
104
- const indexesWithinAncestors = new Map<string, number>([
105
- ["content1", 0],
106
- ["content2", 1],
107
-
108
- ]);
109
-
110
- const rawExecuteComputingExpressions = (
111
- _variables: Map<string, unknown>
112
- ): Map<string, unknown> => {
113
- return new Map([
114
- ]);
115
- };
116
- const executeComputingExpressions = (variables: Map<string, unknown>) => {
117
- const encodedvariables = sdk.encodeVariablesMap(variables);
118
- const encodedResult = rawExecuteComputingExpressions(encodedvariables);
119
- return sdk.decodeVariablesMap(encodedResult);
120
- };
121
-
122
- const generatedEffectfulExpressions = new Map<
123
- string,
124
- (args: Map<string, any>, variables: Map<string, any>) => Map<string, unknown>
125
- >([
126
- ["$ws$dataSource$tabsOpen = open", (_args: Map<string, any>, _variables: Map<string, any>) => { let open = _args.get('open');
127
- let $ws$dataSource$tabsOpen;
128
- $ws$dataSource$tabsOpen = open;
129
- return new Map([
130
- ['$ws$dataSource$tabsOpen', $ws$dataSource$tabsOpen],
131
- ]); }],
132
-
133
- ]);
134
-
135
- const rawExecuteEffectfulExpression = (
136
- code: string,
137
- args: Map<string, unknown>,
138
- variables: Map<string, unknown>
139
- ): Map<string, unknown> => {
140
- if(generatedEffectfulExpressions.has(code)) {
141
- return generatedEffectfulExpressions.get(code)!(args, variables);
142
- }
143
- console.error("Effectful expression not found", code);
144
- throw new Error("Effectful expression not found");
145
- };
146
-
147
- const executeEffectfulExpression = (
148
- code: string,
149
- args: Map<string, unknown>,
150
- variables: Map<string, unknown>
151
- ) => {
152
- const encodedvariables = sdk.encodeVariablesMap(variables);
153
- const encodedResult = rawExecuteEffectfulExpression(code, args, encodedvariables);
154
- return sdk.decodeVariablesMap(encodedResult);
155
- };
156
-
157
- export const utils = {
158
- indexesWithinAncestors,
159
- executeComputingExpressions,
160
- executeEffectfulExpression,
161
- };
162
-
163
- /* eslint-enable */
164
- "
165
- `);
166
- });
package/lib/hook.js DELETED
@@ -1,12 +0,0 @@
1
- "use strict";
2
- export const getClosestInstance = (instancePath, currentInstance, closestComponent) => {
3
- let matched = false;
4
- for (const instance of instancePath) {
5
- if (currentInstance === instance) {
6
- matched = true;
7
- }
8
- if (matched && instance.component === closestComponent) {
9
- return instance;
10
- }
11
- }
12
- };
package/lib/hook.test.js DELETED
@@ -1,15 +0,0 @@
1
- "use strict";
2
- import { expect, test } from "@jest/globals";
3
- import { getClosestInstance } from ".";
4
- test("get closest instance", () => {
5
- const instancePath = [
6
- { type: "instance", id: "4", component: "Content", children: [] },
7
- { type: "instance", id: "3", component: "Tabs", children: [] },
8
- { type: "instance", id: "2", component: "Content", children: [] },
9
- { type: "instance", id: "1", component: "Tabs", children: [] },
10
- { type: "instance", id: "0", component: "Body", children: [] }
11
- ];
12
- const [content2, tabs2, content1, tabs1, _body] = instancePath;
13
- expect(getClosestInstance(instancePath, content2, "Tabs")).toBe(tabs2);
14
- expect(getClosestInstance(instancePath, content1, "Tabs")).toBe(tabs1);
15
- });
@@ -1,43 +0,0 @@
1
- "use strict";
2
- export const getIndexesWithinAncestors = (metas, instances, rootIds) => {
3
- const ancestors = /* @__PURE__ */ new Set();
4
- for (const meta of metas.values()) {
5
- if (meta.indexWithinAncestor !== void 0) {
6
- ancestors.add(meta.indexWithinAncestor);
7
- }
8
- }
9
- const indexes = /* @__PURE__ */ new Map();
10
- const traverseInstances = (instances2, instanceId, latestIndexes2 = /* @__PURE__ */ new Map()) => {
11
- const instance = instances2.get(instanceId);
12
- if (instance === void 0) {
13
- return;
14
- }
15
- const meta = metas.get(instance.component);
16
- if (meta === void 0) {
17
- return;
18
- }
19
- if (ancestors.has(instance.component)) {
20
- latestIndexes2 = new Map(latestIndexes2);
21
- latestIndexes2.set(instance.component, /* @__PURE__ */ new Map());
22
- }
23
- if (meta.indexWithinAncestor !== void 0) {
24
- const ancestorIndexes = latestIndexes2.get(meta.indexWithinAncestor);
25
- if (ancestorIndexes !== void 0) {
26
- let index = ancestorIndexes.get(instance.component) ?? -1;
27
- index += 1;
28
- ancestorIndexes.set(instance.component, index);
29
- indexes.set(instance.id, index);
30
- }
31
- }
32
- for (const child of instance.children) {
33
- if (child.type === "id") {
34
- traverseInstances(instances2, child.value, latestIndexes2);
35
- }
36
- }
37
- };
38
- const latestIndexes = /* @__PURE__ */ new Map();
39
- for (const instanceId of rootIds) {
40
- traverseInstances(instances, instanceId, latestIndexes);
41
- }
42
- return indexes;
43
- };
@@ -1,65 +0,0 @@
1
- "use strict";
2
- import { test, expect } from "@jest/globals";
3
- import { getIndexesWithinAncestors } from "./instance-utils";
4
- const getIdValuePair = (item) => [item.id, item];
5
- const toMap = (list) => new Map(list.map(getIdValuePair));
6
- const createInstance = (id, component, children) => {
7
- return { type: "instance", id, component, children };
8
- };
9
- const createMeta = (meta) => {
10
- return { type: "container", label: "", icon: "", ...meta };
11
- };
12
- test("get indexes within ancestors", () => {
13
- const instances = toMap([
14
- createInstance("body0", "Body", [{ type: "id", value: "tabs1" }]),
15
- // tabs1
16
- createInstance("tabs1", "Tabs", [
17
- { type: "id", value: "tabs1list" },
18
- { type: "id", value: "tabs1content1" },
19
- { type: "id", value: "tabs1content2" }
20
- ]),
21
- createInstance("tabs1list", "TabsList", [
22
- { type: "id", value: "tabs1box" }
23
- ]),
24
- createInstance("tabs1box", "Box", [
25
- { type: "id", value: "tabs1trigger1" },
26
- { type: "id", value: "tabs1trigger2" }
27
- ]),
28
- createInstance("tabs1trigger1", "TabsTrigger", []),
29
- createInstance("tabs1trigger2", "TabsTrigger", []),
30
- createInstance("tabs1content1", "TabsContent", [
31
- { type: "id", value: "tabs2" }
32
- ]),
33
- createInstance("tabs1content2", "TabsContent", []),
34
- // tabs2
35
- createInstance("tabs2", "Tabs", [
36
- { type: "id", value: "tabs2list" },
37
- { type: "id", value: "tabs2content1" }
38
- ]),
39
- createInstance("tabs2list", "TabsList", [
40
- { type: "id", value: "tabs2trigger1" }
41
- ]),
42
- createInstance("tabs2trigger1", "TabsTrigger", []),
43
- createInstance("tabs2content1", "TabsContent", [])
44
- ]);
45
- const metas = /* @__PURE__ */ new Map([
46
- ["Body", createMeta()],
47
- ["Box", createMeta()],
48
- ["Tabs", createMeta()],
49
- ["TabsList", createMeta({ indexWithinAncestor: "Tabs" })],
50
- ["TabsTrigger", createMeta({ indexWithinAncestor: "TabsList" })],
51
- ["TabsContent", createMeta({ indexWithinAncestor: "Tabs" })]
52
- ]);
53
- expect(getIndexesWithinAncestors(metas, instances, ["body0"])).toEqual(
54
- /* @__PURE__ */ new Map([
55
- ["tabs1list", 0],
56
- ["tabs1trigger1", 0],
57
- ["tabs1trigger2", 1],
58
- ["tabs1content1", 0],
59
- ["tabs1content2", 1],
60
- ["tabs2list", 0],
61
- ["tabs2trigger1", 0],
62
- ["tabs2content1", 0]
63
- ])
64
- );
65
- });
package/lib/prop-meta.js DELETED
@@ -1,150 +0,0 @@
1
- "use strict";
2
- import { z } from "zod";
3
- const common = {
4
- label: z.string().optional(),
5
- description: z.string().optional(),
6
- required: z.boolean()
7
- };
8
- const Number = z.object({
9
- ...common,
10
- control: z.literal("number"),
11
- type: z.literal("number"),
12
- defaultValue: z.number().optional()
13
- });
14
- const Range = z.object({
15
- ...common,
16
- control: z.literal("range"),
17
- type: z.literal("number"),
18
- defaultValue: z.number().optional()
19
- });
20
- const Text = z.object({
21
- ...common,
22
- control: z.literal("text"),
23
- type: z.literal("string"),
24
- defaultValue: z.string().optional(),
25
- /**
26
- * The number of rows in <textarea>. If set to 0 an <input> will be used instead.
27
- * In line with Storybook team's plan: https://github.com/storybookjs/storybook/issues/21100
28
- */
29
- rows: z.number().optional()
30
- });
31
- const Code = z.object({
32
- ...common,
33
- control: z.literal("code"),
34
- type: z.literal("string"),
35
- defaultValue: z.string().optional(),
36
- /**
37
- * The number of rows in <textarea>. If set to 0 an <input> will be used instead.
38
- * In line with Storybook team's plan: https://github.com/storybookjs/storybook/issues/21100
39
- */
40
- rows: z.number().optional()
41
- });
42
- const Color = z.object({
43
- ...common,
44
- control: z.literal("color"),
45
- type: z.literal("string"),
46
- defaultValue: z.string().optional()
47
- });
48
- const Boolean = z.object({
49
- ...common,
50
- control: z.literal("boolean"),
51
- type: z.literal("boolean"),
52
- defaultValue: z.boolean().optional()
53
- });
54
- const Radio = z.object({
55
- ...common,
56
- control: z.literal("radio"),
57
- type: z.literal("string"),
58
- defaultValue: z.string().optional(),
59
- options: z.array(z.string())
60
- });
61
- const InlineRadio = z.object({
62
- ...common,
63
- control: z.literal("inline-radio"),
64
- type: z.literal("string"),
65
- defaultValue: z.string().optional(),
66
- options: z.array(z.string())
67
- });
68
- const Select = z.object({
69
- ...common,
70
- control: z.literal("select"),
71
- type: z.literal("string"),
72
- defaultValue: z.string().optional(),
73
- options: z.array(z.string())
74
- });
75
- const Check = z.object({
76
- ...common,
77
- control: z.literal("check"),
78
- type: z.literal("string[]"),
79
- defaultValue: z.array(z.string()).optional(),
80
- options: z.array(z.string())
81
- });
82
- const InlineCheck = z.object({
83
- ...common,
84
- control: z.literal("inline-check"),
85
- type: z.literal("string[]"),
86
- defaultValue: z.array(z.string()).optional(),
87
- options: z.array(z.string())
88
- });
89
- const MultiSelect = z.object({
90
- ...common,
91
- control: z.literal("multi-select"),
92
- type: z.literal("string[]"),
93
- defaultValue: z.array(z.string()).optional(),
94
- options: z.array(z.string())
95
- });
96
- const File = z.object({
97
- ...common,
98
- control: z.literal("file"),
99
- type: z.literal("string"),
100
- defaultValue: z.string().optional(),
101
- /** https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept */
102
- accept: z.string().optional()
103
- });
104
- const Url = z.object({
105
- ...common,
106
- control: z.literal("url"),
107
- type: z.literal("string"),
108
- defaultValue: z.string().optional()
109
- });
110
- const ObjectType = z.object({
111
- ...common,
112
- control: z.literal("object"),
113
- // @todo not sure what type should be here
114
- // (we don't support Object yet, added for completeness)
115
- type: z.literal("Record<string, string>"),
116
- defaultValue: z.record(z.string()).optional()
117
- });
118
- const Date = z.object({
119
- ...common,
120
- control: z.literal("date"),
121
- // @todo not sure what type should be here
122
- // (we don't support Date yet, added for completeness)
123
- type: z.literal("string"),
124
- defaultValue: z.string().optional()
125
- });
126
- const Action = z.object({
127
- ...common,
128
- control: z.literal("action"),
129
- type: z.literal("action"),
130
- defaultValue: z.undefined().optional()
131
- });
132
- export const PropMeta = z.union([
133
- Number,
134
- Range,
135
- Text,
136
- Code,
137
- Color,
138
- Boolean,
139
- Radio,
140
- InlineRadio,
141
- Select,
142
- MultiSelect,
143
- Check,
144
- InlineCheck,
145
- File,
146
- Url,
147
- ObjectType,
148
- Date,
149
- Action
150
- ]);