@webstudio-is/react-sdk 0.91.0 → 0.92.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.
- package/lib/app/index.js +1 -0
- package/lib/app/root.js +2 -4
- package/lib/component-renderer.js +3 -5
- package/lib/components/component-meta.js +6 -11
- package/lib/components/components-utils.js +1 -0
- package/lib/context.js +2 -4
- package/lib/css/css.js +4 -9
- package/lib/css/global-rules.js +3 -5
- package/lib/css/index.js +1 -0
- package/lib/css/normalize-type-check.js +1 -0
- package/lib/css/normalize.js +48 -96
- package/lib/css/presets.js +3 -6
- package/lib/css/style-rules.js +3 -6
- package/{src/css/style-rules.test.ts → lib/css/style-rules.test.js} +23 -28
- package/lib/embed-template.js +7 -22
- package/{src/embed-template.test.ts → lib/embed-template.test.js} +165 -176
- package/lib/expression.js +11 -22
- package/{src/expression.test.ts → lib/expression.test.js} +55 -83
- package/lib/generator.js +2 -4
- package/{src/generator.test.ts → lib/generator.test.js} +28 -31
- package/lib/hook.js +2 -4
- package/{src/hook.test.ts → lib/hook.test.js} +4 -4
- package/lib/index.js +9 -31
- package/lib/instance-utils.js +2 -4
- package/{src/instance-utils.test.ts → lib/instance-utils.test.js} +19 -43
- package/lib/prop-meta.js +150 -0
- package/lib/props.js +8 -16
- package/{src/props.test.ts → lib/props.test.js} +39 -68
- package/lib/pubsub/create.js +2 -4
- package/lib/pubsub/index.js +1 -0
- package/lib/pubsub/raf-queue.js +2 -4
- package/lib/tree/create-elements-tree.js +2 -4
- package/lib/tree/index.js +1 -0
- package/lib/tree/root.js +2 -5
- package/lib/tree/webstudio-component.js +10 -20
- package/lib/types/component-renderer.d.ts +1 -1
- package/lib/types/components/component-meta.d.ts +526 -526
- package/lib/types/context.d.ts +1 -2
- package/lib/types/css/css.d.ts +22 -23
- package/lib/types/css/global-rules.d.ts +19 -19
- package/lib/types/css/normalize.d.ts +2444 -2444
- package/lib/types/css/style-rules.d.ts +2 -2
- package/lib/types/embed-template.d.ts +648 -648
- package/lib/types/generator.d.ts +1 -1
- package/lib/types/hook.d.ts +3 -3
- package/lib/types/index.d.ts +1 -0
- package/lib/types/instance-utils.d.ts +3 -3
- package/lib/types/prop-meta.d.ts +396 -0
- package/lib/types/props.d.ts +52 -53
- package/lib/types/tree/create-elements-tree.d.ts +3 -4
- package/lib/types/tree/root.d.ts +8 -8
- package/lib/types/tree/webstudio-component.d.ts +1 -1
- package/package.json +14 -22
- package/lib/cjs/app/index.js +0 -18
- package/lib/cjs/app/root.js +0 -40
- package/lib/cjs/component-renderer.js +0 -143
- package/lib/cjs/components/component-meta.js +0 -87
- package/lib/cjs/components/components-utils.js +0 -17
- package/lib/cjs/context.js +0 -43
- package/lib/cjs/css/css.js +0 -84
- package/lib/cjs/css/global-rules.js +0 -37
- package/lib/cjs/css/index.js +0 -20
- package/lib/cjs/css/normalize-type-check.js +0 -26
- package/lib/cjs/css/normalize.js +0 -349
- package/lib/cjs/css/presets.js +0 -48
- package/lib/cjs/css/style-rules.js +0 -86
- package/lib/cjs/embed-template.js +0 -368
- package/lib/cjs/expression.js +0 -371
- package/lib/cjs/generator.js +0 -128
- package/lib/cjs/hook.js +0 -34
- package/lib/cjs/index.js +0 -59
- package/lib/cjs/instance-utils.js +0 -65
- package/lib/cjs/package.json +0 -1
- package/lib/cjs/props.js +0 -204
- package/lib/cjs/pubsub/create.js +0 -78
- package/lib/cjs/pubsub/index.js +0 -18
- package/lib/cjs/pubsub/raf-queue.js +0 -42
- package/lib/cjs/tree/create-elements-tree.js +0 -152
- package/lib/cjs/tree/index.js +0 -20
- package/lib/cjs/tree/root.js +0 -100
- package/lib/cjs/tree/webstudio-component.js +0 -91
- package/src/app/index.ts +0 -1
- package/src/app/root.tsx +0 -25
- package/src/component-renderer.tsx +0 -146
- package/src/components/component-meta.ts +0 -86
- package/src/components/components-utils.ts +0 -13
- package/src/context.tsx +0 -73
- package/src/css/css.ts +0 -88
- package/src/css/global-rules.ts +0 -26
- package/src/css/index.ts +0 -3
- package/src/css/normalize-type-check.ts +0 -13
- package/src/css/normalize.ts +0 -507
- package/src/css/presets.ts +0 -27
- package/src/css/style-rules.ts +0 -101
- package/src/embed-template.ts +0 -438
- package/src/expression.ts +0 -401
- package/src/generator.ts +0 -147
- package/src/hook.ts +0 -52
- package/src/index.ts +0 -39
- package/src/instance-utils.ts +0 -65
- package/src/props.ts +0 -231
- package/src/pubsub/create.ts +0 -77
- package/src/pubsub/index.ts +0 -1
- package/src/pubsub/raf-queue.ts +0 -25
- package/src/tree/create-elements-tree.tsx +0 -186
- package/src/tree/index.ts +0 -3
- package/src/tree/root.ts +0 -131
- package/src/tree/webstudio-component.tsx +0 -97
package/src/expression.ts
DELETED
|
@@ -1,401 +0,0 @@
|
|
|
1
|
-
import jsep from "jsep";
|
|
2
|
-
import jsepAssignment from "@jsep-plugin/assignment";
|
|
3
|
-
import type {
|
|
4
|
-
UpdateExpression,
|
|
5
|
-
AssignmentExpression,
|
|
6
|
-
} from "@jsep-plugin/assignment";
|
|
7
|
-
|
|
8
|
-
jsep.plugins.register(jsepAssignment);
|
|
9
|
-
|
|
10
|
-
type TransformIdentifier = (id: string, assignee: boolean) => string;
|
|
11
|
-
|
|
12
|
-
type Node = jsep.CoreExpression | UpdateExpression | AssignmentExpression;
|
|
13
|
-
|
|
14
|
-
const generateCode = (
|
|
15
|
-
node: Node,
|
|
16
|
-
failOnForbidden: boolean,
|
|
17
|
-
effectful: boolean,
|
|
18
|
-
transformIdentifier: TransformIdentifier
|
|
19
|
-
): string => {
|
|
20
|
-
if (node.type === "Identifier") {
|
|
21
|
-
return transformIdentifier(node.name, false);
|
|
22
|
-
}
|
|
23
|
-
if (node.type === "MemberExpression") {
|
|
24
|
-
if (failOnForbidden) {
|
|
25
|
-
const object = generateCode(
|
|
26
|
-
node.object as Node,
|
|
27
|
-
false,
|
|
28
|
-
effectful,
|
|
29
|
-
transformIdentifier
|
|
30
|
-
);
|
|
31
|
-
const property = generateCode(
|
|
32
|
-
node.property as Node,
|
|
33
|
-
false,
|
|
34
|
-
effectful,
|
|
35
|
-
transformIdentifier
|
|
36
|
-
);
|
|
37
|
-
throw Error(`Cannot access "${property}" of "${object}"`);
|
|
38
|
-
}
|
|
39
|
-
const object = generateCode(
|
|
40
|
-
node.object as Node,
|
|
41
|
-
failOnForbidden,
|
|
42
|
-
effectful,
|
|
43
|
-
transformIdentifier
|
|
44
|
-
);
|
|
45
|
-
const property = generateCode(
|
|
46
|
-
node.property as Node,
|
|
47
|
-
failOnForbidden,
|
|
48
|
-
effectful,
|
|
49
|
-
transformIdentifier
|
|
50
|
-
);
|
|
51
|
-
return `${object}.${property}`;
|
|
52
|
-
}
|
|
53
|
-
if (node.type === "Literal") {
|
|
54
|
-
return node.raw;
|
|
55
|
-
}
|
|
56
|
-
if (node.type === "UnaryExpression") {
|
|
57
|
-
const arg = generateCode(
|
|
58
|
-
node.argument as Node,
|
|
59
|
-
failOnForbidden,
|
|
60
|
-
effectful,
|
|
61
|
-
transformIdentifier
|
|
62
|
-
);
|
|
63
|
-
return `${node.operator}${arg}`;
|
|
64
|
-
}
|
|
65
|
-
if (node.type === "BinaryExpression") {
|
|
66
|
-
const left = generateCode(
|
|
67
|
-
node.left as Node,
|
|
68
|
-
failOnForbidden,
|
|
69
|
-
effectful,
|
|
70
|
-
transformIdentifier
|
|
71
|
-
);
|
|
72
|
-
const right = generateCode(
|
|
73
|
-
node.right as Node,
|
|
74
|
-
failOnForbidden,
|
|
75
|
-
effectful,
|
|
76
|
-
transformIdentifier
|
|
77
|
-
);
|
|
78
|
-
return `${left} ${node.operator} ${right}`;
|
|
79
|
-
}
|
|
80
|
-
if (node.type === "ArrayExpression") {
|
|
81
|
-
const elements = node.elements.map((element) =>
|
|
82
|
-
generateCode(
|
|
83
|
-
element as Node,
|
|
84
|
-
failOnForbidden,
|
|
85
|
-
effectful,
|
|
86
|
-
transformIdentifier
|
|
87
|
-
)
|
|
88
|
-
);
|
|
89
|
-
return `[${elements.join(", ")}]`;
|
|
90
|
-
}
|
|
91
|
-
if (node.type === "CallExpression") {
|
|
92
|
-
if (failOnForbidden) {
|
|
93
|
-
const callee = generateCode(
|
|
94
|
-
node.callee as Node,
|
|
95
|
-
false,
|
|
96
|
-
effectful,
|
|
97
|
-
transformIdentifier
|
|
98
|
-
);
|
|
99
|
-
throw Error(`Cannot call "${callee}"`);
|
|
100
|
-
}
|
|
101
|
-
const callee = generateCode(
|
|
102
|
-
node.callee as Node,
|
|
103
|
-
failOnForbidden,
|
|
104
|
-
effectful,
|
|
105
|
-
transformIdentifier
|
|
106
|
-
);
|
|
107
|
-
const args = node.arguments.map((arg) =>
|
|
108
|
-
generateCode(arg as Node, failOnForbidden, effectful, transformIdentifier)
|
|
109
|
-
);
|
|
110
|
-
return `${callee}(${args.join(", ")})`;
|
|
111
|
-
}
|
|
112
|
-
if (node.type === "ThisExpression") {
|
|
113
|
-
if (failOnForbidden) {
|
|
114
|
-
throw Error(`"this" is not supported`);
|
|
115
|
-
}
|
|
116
|
-
return "this";
|
|
117
|
-
}
|
|
118
|
-
if (node.type === "ConditionalExpression") {
|
|
119
|
-
throw Error("Ternary operator is not supported");
|
|
120
|
-
}
|
|
121
|
-
if (node.type === "Compound") {
|
|
122
|
-
throw Error("Cannot use multiple expressions");
|
|
123
|
-
}
|
|
124
|
-
if (node.type === "AssignmentExpression") {
|
|
125
|
-
if (node.operator !== "=") {
|
|
126
|
-
throw Error(`Only "=" assignment operator is supported`);
|
|
127
|
-
}
|
|
128
|
-
if (effectful === false) {
|
|
129
|
-
throw Error(`Cannot use assignment in this expression`);
|
|
130
|
-
}
|
|
131
|
-
const left = generateCode(
|
|
132
|
-
node.left as Node,
|
|
133
|
-
failOnForbidden,
|
|
134
|
-
effectful,
|
|
135
|
-
// override and mark all identifiers inside of left expression as assignee
|
|
136
|
-
(id) => transformIdentifier(id, true)
|
|
137
|
-
);
|
|
138
|
-
const right = generateCode(
|
|
139
|
-
node.right as Node,
|
|
140
|
-
failOnForbidden,
|
|
141
|
-
effectful,
|
|
142
|
-
transformIdentifier
|
|
143
|
-
);
|
|
144
|
-
return `${left} ${node.operator} ${right}`;
|
|
145
|
-
}
|
|
146
|
-
if (node.type === "UpdateExpression") {
|
|
147
|
-
throw Error(`"${node.operator}" operator is not supported`);
|
|
148
|
-
}
|
|
149
|
-
node satisfies never;
|
|
150
|
-
return "";
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
export const validateExpression = (
|
|
154
|
-
code: string,
|
|
155
|
-
options?: { effectful?: boolean; transformIdentifier?: TransformIdentifier }
|
|
156
|
-
) => {
|
|
157
|
-
const { effectful = false, transformIdentifier = (id: string) => id } =
|
|
158
|
-
options ?? {};
|
|
159
|
-
const expression = jsep(code) as Node;
|
|
160
|
-
return generateCode(expression, true, effectful, transformIdentifier);
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
const sortTopologically = (
|
|
164
|
-
list: Set<string>,
|
|
165
|
-
depsById: Map<string, Set<string>>,
|
|
166
|
-
explored = new Set<string>(),
|
|
167
|
-
sorted: string[] = []
|
|
168
|
-
) => {
|
|
169
|
-
for (const id of list) {
|
|
170
|
-
if (explored.has(id)) {
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
173
|
-
explored.add(id);
|
|
174
|
-
const deps = depsById.get(id);
|
|
175
|
-
if (deps) {
|
|
176
|
-
sortTopologically(deps, depsById, explored, sorted);
|
|
177
|
-
}
|
|
178
|
-
sorted.push(id);
|
|
179
|
-
}
|
|
180
|
-
return sorted;
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Generates a function body expecting map as _variables argument
|
|
185
|
-
* and outputing map of results
|
|
186
|
-
*/
|
|
187
|
-
export const generateComputingExpressions = (
|
|
188
|
-
expressions: Map<string, string>,
|
|
189
|
-
allowedVariables: Set<string>
|
|
190
|
-
) => {
|
|
191
|
-
const depsById = new Map<string, Set<string>>();
|
|
192
|
-
const inputVariables = new Set<string>();
|
|
193
|
-
for (const [id, code] of expressions) {
|
|
194
|
-
const deps = new Set<string>();
|
|
195
|
-
validateExpression(code, {
|
|
196
|
-
transformIdentifier: (identifier) => {
|
|
197
|
-
if (allowedVariables.has(identifier)) {
|
|
198
|
-
inputVariables.add(identifier);
|
|
199
|
-
return identifier;
|
|
200
|
-
}
|
|
201
|
-
if (expressions.has(identifier)) {
|
|
202
|
-
deps.add(identifier);
|
|
203
|
-
return identifier;
|
|
204
|
-
}
|
|
205
|
-
throw Error(`Unknown dependency "${identifier}"`);
|
|
206
|
-
},
|
|
207
|
-
});
|
|
208
|
-
depsById.set(id, deps);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const sortedExpressions = sortTopologically(
|
|
212
|
-
new Set(expressions.keys()),
|
|
213
|
-
depsById
|
|
214
|
-
);
|
|
215
|
-
|
|
216
|
-
// generate code computing all expressions
|
|
217
|
-
let generatedCode = "";
|
|
218
|
-
|
|
219
|
-
for (const id of inputVariables) {
|
|
220
|
-
generatedCode += `const ${id} = _variables.get('${id}');\n`;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
for (const id of sortedExpressions) {
|
|
224
|
-
const code = expressions.get(id);
|
|
225
|
-
if (code === undefined) {
|
|
226
|
-
continue;
|
|
227
|
-
}
|
|
228
|
-
generatedCode += `const ${id} = (${code});\n`;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
generatedCode += `return new Map([\n`;
|
|
232
|
-
for (const id of sortedExpressions) {
|
|
233
|
-
generatedCode += ` ['${id}', ${id}],\n`;
|
|
234
|
-
}
|
|
235
|
-
generatedCode += `]);`;
|
|
236
|
-
|
|
237
|
-
return generatedCode;
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
export const executeComputingExpressions = (
|
|
241
|
-
expressions: Map<string, string>,
|
|
242
|
-
variables: Map<string, unknown>
|
|
243
|
-
) => {
|
|
244
|
-
const generatedCode = generateComputingExpressions(
|
|
245
|
-
expressions,
|
|
246
|
-
new Set(variables.keys())
|
|
247
|
-
);
|
|
248
|
-
const executeFn = new Function("_variables", generatedCode);
|
|
249
|
-
const values = executeFn(variables) as Map<string, unknown>;
|
|
250
|
-
return values;
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
export const generateEffectfulExpression = (
|
|
254
|
-
code: string,
|
|
255
|
-
args: Set<string>,
|
|
256
|
-
allowedVariables: Set<string>
|
|
257
|
-
) => {
|
|
258
|
-
const inputVariables = new Set<string>();
|
|
259
|
-
const outputVariables = new Set<string>();
|
|
260
|
-
validateExpression(code, {
|
|
261
|
-
effectful: true,
|
|
262
|
-
transformIdentifier: (identifier, assignee) => {
|
|
263
|
-
if (args.has(identifier)) {
|
|
264
|
-
return identifier;
|
|
265
|
-
}
|
|
266
|
-
if (allowedVariables.has(identifier)) {
|
|
267
|
-
if (assignee) {
|
|
268
|
-
outputVariables.add(identifier);
|
|
269
|
-
} else {
|
|
270
|
-
inputVariables.add(identifier);
|
|
271
|
-
}
|
|
272
|
-
return identifier;
|
|
273
|
-
}
|
|
274
|
-
throw Error(`Unknown dependency "${identifier}"`);
|
|
275
|
-
},
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
// generate code computing all expressions
|
|
279
|
-
let generatedCode = "";
|
|
280
|
-
|
|
281
|
-
for (const id of args) {
|
|
282
|
-
generatedCode += `let ${id} = _args.get('${id}');\n`;
|
|
283
|
-
}
|
|
284
|
-
for (const id of inputVariables) {
|
|
285
|
-
generatedCode += `let ${id} = _variables.get('${id}');\n`;
|
|
286
|
-
}
|
|
287
|
-
for (const id of outputVariables) {
|
|
288
|
-
if (inputVariables.has(id) === false) {
|
|
289
|
-
generatedCode += `let ${id};\n`;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
generatedCode += `${code};\n`;
|
|
294
|
-
|
|
295
|
-
generatedCode += `return new Map([\n`;
|
|
296
|
-
for (const id of outputVariables) {
|
|
297
|
-
generatedCode += ` ['${id}', ${id}],\n`;
|
|
298
|
-
}
|
|
299
|
-
generatedCode += `]);`;
|
|
300
|
-
|
|
301
|
-
return generatedCode;
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
export const executeEffectfulExpression = (
|
|
305
|
-
code: string,
|
|
306
|
-
args: Map<string, unknown>,
|
|
307
|
-
variables: Map<string, unknown>
|
|
308
|
-
) => {
|
|
309
|
-
const generatedCode = generateEffectfulExpression(
|
|
310
|
-
code,
|
|
311
|
-
new Set(args.keys()),
|
|
312
|
-
new Set(variables.keys())
|
|
313
|
-
);
|
|
314
|
-
const executeFn = new Function("_variables", "_args", generatedCode);
|
|
315
|
-
const values = executeFn(variables, args) as Map<string, unknown>;
|
|
316
|
-
return values;
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
const computeExpressionDependencies = (
|
|
320
|
-
expressions: Map<string, string>,
|
|
321
|
-
expressionId: string,
|
|
322
|
-
dependencies: Map<string, Set<string>>
|
|
323
|
-
) => {
|
|
324
|
-
// prevent recalculating expressions over again
|
|
325
|
-
const depsById = dependencies.get(expressionId);
|
|
326
|
-
if (depsById) {
|
|
327
|
-
return depsById;
|
|
328
|
-
}
|
|
329
|
-
const parentDeps = new Set<string>();
|
|
330
|
-
const code = expressions.get(expressionId);
|
|
331
|
-
if (code === undefined) {
|
|
332
|
-
return parentDeps;
|
|
333
|
-
}
|
|
334
|
-
// write before recursive call to avoid infinite cycle
|
|
335
|
-
dependencies.set(expressionId, parentDeps);
|
|
336
|
-
validateExpression(code, {
|
|
337
|
-
transformIdentifier: (id) => {
|
|
338
|
-
parentDeps.add(id);
|
|
339
|
-
const childDeps = computeExpressionDependencies(
|
|
340
|
-
expressions,
|
|
341
|
-
id,
|
|
342
|
-
dependencies
|
|
343
|
-
);
|
|
344
|
-
for (const depId of childDeps) {
|
|
345
|
-
parentDeps.add(depId);
|
|
346
|
-
}
|
|
347
|
-
return id;
|
|
348
|
-
},
|
|
349
|
-
});
|
|
350
|
-
return parentDeps;
|
|
351
|
-
};
|
|
352
|
-
|
|
353
|
-
export const computeExpressionsDependencies = (
|
|
354
|
-
expressions: Map<string, string>
|
|
355
|
-
) => {
|
|
356
|
-
const dependencies = new Map<string, Set<string>>();
|
|
357
|
-
for (const id of expressions.keys()) {
|
|
358
|
-
computeExpressionDependencies(expressions, id, dependencies);
|
|
359
|
-
}
|
|
360
|
-
return dependencies;
|
|
361
|
-
};
|
|
362
|
-
|
|
363
|
-
type Values = Map<string, unknown>;
|
|
364
|
-
|
|
365
|
-
const dataSourceVariablePrefix = "$ws$dataSource$";
|
|
366
|
-
|
|
367
|
-
// data source id is generated with nanoid which has "-" in alphabeta
|
|
368
|
-
// here "-" is encoded with "__DASH__' in variable name
|
|
369
|
-
// https://github.com/ai/nanoid/blob/047686abad8f15aff05f3a2eeedb7c98b6847392/url-alphabet/index.js
|
|
370
|
-
|
|
371
|
-
export const encodeDataSourceVariable = (id: string) => {
|
|
372
|
-
const encoded = id.replaceAll("-", "__DASH__");
|
|
373
|
-
return `${dataSourceVariablePrefix}${encoded}`;
|
|
374
|
-
};
|
|
375
|
-
|
|
376
|
-
export const encodeVariablesMap = (values: Values) => {
|
|
377
|
-
const encodedValues: Values = new Map();
|
|
378
|
-
for (const [id, value] of values) {
|
|
379
|
-
encodedValues.set(encodeDataSourceVariable(id), value);
|
|
380
|
-
}
|
|
381
|
-
return encodedValues;
|
|
382
|
-
};
|
|
383
|
-
|
|
384
|
-
export const decodeDataSourceVariable = (name: string) => {
|
|
385
|
-
if (name.startsWith(dataSourceVariablePrefix)) {
|
|
386
|
-
const encoded = name.slice(dataSourceVariablePrefix.length);
|
|
387
|
-
return encoded.replaceAll("__DASH__", "-");
|
|
388
|
-
}
|
|
389
|
-
return;
|
|
390
|
-
};
|
|
391
|
-
|
|
392
|
-
export const decodeVariablesMap = (values: Values) => {
|
|
393
|
-
const decodedValues: Values = new Map();
|
|
394
|
-
for (const [name, value] of values) {
|
|
395
|
-
const id = decodeDataSourceVariable(name);
|
|
396
|
-
if (id !== undefined) {
|
|
397
|
-
decodedValues.set(id, value);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
return decodedValues;
|
|
401
|
-
};
|
package/src/generator.ts
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
DataSources,
|
|
3
|
-
Instance,
|
|
4
|
-
Instances,
|
|
5
|
-
Page,
|
|
6
|
-
Props,
|
|
7
|
-
} from "@webstudio-is/project-build";
|
|
8
|
-
import type { WsComponentMeta } from "./components/component-meta";
|
|
9
|
-
import {
|
|
10
|
-
getIndexesWithinAncestors,
|
|
11
|
-
type IndexesWithinAncestors,
|
|
12
|
-
} from "./instance-utils";
|
|
13
|
-
import {
|
|
14
|
-
encodeDataSourceVariable,
|
|
15
|
-
generateComputingExpressions,
|
|
16
|
-
generateEffectfulExpression,
|
|
17
|
-
} from "./expression";
|
|
18
|
-
import type { DataSourceValues } from "./context";
|
|
19
|
-
|
|
20
|
-
type PageData = {
|
|
21
|
-
page: Page;
|
|
22
|
-
metas: Map<Instance["component"], WsComponentMeta>;
|
|
23
|
-
instances: Instances;
|
|
24
|
-
props: Props;
|
|
25
|
-
dataSources: DataSources;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export type GeneratedUtils = {
|
|
29
|
-
indexesWithinAncestors: IndexesWithinAncestors;
|
|
30
|
-
executeComputingExpressions: (values: DataSourceValues) => DataSourceValues;
|
|
31
|
-
executeEffectfulExpression: (
|
|
32
|
-
expression: string,
|
|
33
|
-
args: DataSourceValues,
|
|
34
|
-
values: DataSourceValues
|
|
35
|
-
) => DataSourceValues;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Generates data based utilities at build time
|
|
40
|
-
* Requires this import statement in scope
|
|
41
|
-
* import * as sdk from "@webstudio-is/react-sdk";
|
|
42
|
-
*/
|
|
43
|
-
export const generateUtilsExport = (siteData: PageData) => {
|
|
44
|
-
const indexesWithinAncestors = getIndexesWithinAncestors(
|
|
45
|
-
siteData.metas,
|
|
46
|
-
siteData.instances,
|
|
47
|
-
[siteData.page.rootInstanceId]
|
|
48
|
-
);
|
|
49
|
-
let indexesWithinAncestorsEntries = "";
|
|
50
|
-
for (const [key, value] of indexesWithinAncestors) {
|
|
51
|
-
const keyString = JSON.stringify(key);
|
|
52
|
-
const valueString = JSON.stringify(value);
|
|
53
|
-
indexesWithinAncestorsEntries += `[${keyString}, ${valueString}],\n`;
|
|
54
|
-
}
|
|
55
|
-
const generatedIndexesWithinAncestors = `
|
|
56
|
-
const indexesWithinAncestors = new Map<string, number>([
|
|
57
|
-
${indexesWithinAncestorsEntries}
|
|
58
|
-
]);
|
|
59
|
-
`;
|
|
60
|
-
|
|
61
|
-
const variables = new Set<string>();
|
|
62
|
-
const expressions = new Map<string, string>();
|
|
63
|
-
for (const dataSource of siteData.dataSources.values()) {
|
|
64
|
-
if (dataSource.type === "variable") {
|
|
65
|
-
variables.add(encodeDataSourceVariable(dataSource.id));
|
|
66
|
-
}
|
|
67
|
-
if (dataSource.type === "expression") {
|
|
68
|
-
expressions.set(encodeDataSourceVariable(dataSource.id), dataSource.code);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
const generatedExecuteComputingExpressions = `
|
|
72
|
-
const rawExecuteComputingExpressions = (
|
|
73
|
-
_variables: Map<string, unknown>
|
|
74
|
-
): Map<string, unknown> => {
|
|
75
|
-
${generateComputingExpressions(expressions, variables)}
|
|
76
|
-
};
|
|
77
|
-
const executeComputingExpressions = (variables: Map<string, unknown>) => {
|
|
78
|
-
const encodedvariables = sdk.encodeVariablesMap(variables);
|
|
79
|
-
const encodedResult = rawExecuteComputingExpressions(encodedvariables);
|
|
80
|
-
return sdk.decodeVariablesMap(encodedResult);
|
|
81
|
-
};
|
|
82
|
-
`;
|
|
83
|
-
|
|
84
|
-
let effectfulExpressionsEntries = "";
|
|
85
|
-
for (const prop of siteData.props.values()) {
|
|
86
|
-
if (prop.type === "action") {
|
|
87
|
-
for (const executableValue of prop.value) {
|
|
88
|
-
const codeString = JSON.stringify(executableValue.code);
|
|
89
|
-
const generatedCode = generateEffectfulExpression(
|
|
90
|
-
executableValue.code,
|
|
91
|
-
new Set(executableValue.args),
|
|
92
|
-
variables
|
|
93
|
-
);
|
|
94
|
-
const generatedFunction = `(_args: Map<string, any>, _variables: Map<string, any>) => { ${generatedCode} }`;
|
|
95
|
-
|
|
96
|
-
effectfulExpressionsEntries += `[${codeString}, ${generatedFunction}],\n`;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
const generatedExecuteEffectfulExpression = `const generatedEffectfulExpressions = new Map<
|
|
101
|
-
string,
|
|
102
|
-
(args: Map<string, any>, variables: Map<string, any>) => Map<string, unknown>
|
|
103
|
-
>([
|
|
104
|
-
${effectfulExpressionsEntries}
|
|
105
|
-
]);
|
|
106
|
-
|
|
107
|
-
const rawExecuteEffectfulExpression = (
|
|
108
|
-
code: string,
|
|
109
|
-
args: Map<string, unknown>,
|
|
110
|
-
variables: Map<string, unknown>
|
|
111
|
-
): Map<string, unknown> => {
|
|
112
|
-
if(generatedEffectfulExpressions.has(code)) {
|
|
113
|
-
return generatedEffectfulExpressions.get(code)!(args, variables);
|
|
114
|
-
}
|
|
115
|
-
console.error("Effectful expression not found", code);
|
|
116
|
-
throw new Error("Effectful expression not found");
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const executeEffectfulExpression = (
|
|
120
|
-
code: string,
|
|
121
|
-
args: Map<string, unknown>,
|
|
122
|
-
variables: Map<string, unknown>
|
|
123
|
-
) => {
|
|
124
|
-
const encodedvariables = sdk.encodeVariablesMap(variables);
|
|
125
|
-
const encodedResult = rawExecuteEffectfulExpression(code, args, encodedvariables);
|
|
126
|
-
return sdk.decodeVariablesMap(encodedResult);
|
|
127
|
-
};
|
|
128
|
-
`;
|
|
129
|
-
|
|
130
|
-
return `
|
|
131
|
-
/* eslint-disable */
|
|
132
|
-
|
|
133
|
-
${generatedIndexesWithinAncestors.trim()}
|
|
134
|
-
|
|
135
|
-
${generatedExecuteComputingExpressions.trim()}
|
|
136
|
-
|
|
137
|
-
${generatedExecuteEffectfulExpression.trim()}
|
|
138
|
-
|
|
139
|
-
export const utils = {
|
|
140
|
-
indexesWithinAncestors,
|
|
141
|
-
executeComputingExpressions,
|
|
142
|
-
executeEffectfulExpression,
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
/* eslint-enable */
|
|
146
|
-
`;
|
|
147
|
-
};
|
package/src/hook.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type { Instance, Prop } from "@webstudio-is/project-build";
|
|
2
|
-
import type { IndexesWithinAncestors } from "./instance-utils";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Hooks are subscriptions to builder events
|
|
6
|
-
* with limited way to interact with it.
|
|
7
|
-
* Called independently from components.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
export type HookContext = {
|
|
11
|
-
indexesWithinAncestors: IndexesWithinAncestors;
|
|
12
|
-
getPropValue: (instanceId: Instance["id"], propName: Prop["name"]) => unknown;
|
|
13
|
-
setPropVariable: (
|
|
14
|
-
instanceId: Instance["id"],
|
|
15
|
-
propName: Prop["name"],
|
|
16
|
-
value: unknown
|
|
17
|
-
) => void;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export type InstancePath = Instance[];
|
|
21
|
-
|
|
22
|
-
type NavigatorEvent = {
|
|
23
|
-
/**
|
|
24
|
-
* List of instances from selected to the root
|
|
25
|
-
*/
|
|
26
|
-
instancePath: InstancePath;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export type Hook = {
|
|
30
|
-
onNavigatorSelect?: (context: HookContext, event: NavigatorEvent) => void;
|
|
31
|
-
onNavigatorUnselect?: (context: HookContext, event: NavigatorEvent) => void;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Find closest matching instance by component name
|
|
36
|
-
* by lookup in instance path
|
|
37
|
-
*/
|
|
38
|
-
export const getClosestInstance = (
|
|
39
|
-
instancePath: InstancePath,
|
|
40
|
-
currentInstance: Instance,
|
|
41
|
-
closestComponent: Instance["component"]
|
|
42
|
-
) => {
|
|
43
|
-
let matched = false;
|
|
44
|
-
for (const instance of instancePath) {
|
|
45
|
-
if (currentInstance === instance) {
|
|
46
|
-
matched = true;
|
|
47
|
-
}
|
|
48
|
-
if (matched && instance.component === closestComponent) {
|
|
49
|
-
return instance;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
};
|
package/src/index.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
export * from "./css";
|
|
2
|
-
export * from "./tree";
|
|
3
|
-
export * from "./pubsub";
|
|
4
|
-
export * from "./app";
|
|
5
|
-
export * from "./components/components-utils";
|
|
6
|
-
export {
|
|
7
|
-
type WsComponentPropsMeta,
|
|
8
|
-
type WsComponentMeta,
|
|
9
|
-
type ComponentState,
|
|
10
|
-
type PresetStyle,
|
|
11
|
-
componentCategories,
|
|
12
|
-
stateCategories,
|
|
13
|
-
defaultStates,
|
|
14
|
-
} from "./components/component-meta";
|
|
15
|
-
export * from "./embed-template";
|
|
16
|
-
export {
|
|
17
|
-
useInstanceProps,
|
|
18
|
-
usePropUrl,
|
|
19
|
-
usePropAsset,
|
|
20
|
-
getInstanceIdFromComponentProps,
|
|
21
|
-
getIndexWithinAncestorFromComponentProps,
|
|
22
|
-
} from "./props";
|
|
23
|
-
export { type Params, ReactSdkContext } from "./context";
|
|
24
|
-
export {
|
|
25
|
-
validateExpression,
|
|
26
|
-
generateComputingExpressions,
|
|
27
|
-
executeComputingExpressions,
|
|
28
|
-
generateEffectfulExpression,
|
|
29
|
-
executeEffectfulExpression,
|
|
30
|
-
computeExpressionsDependencies,
|
|
31
|
-
encodeDataSourceVariable,
|
|
32
|
-
encodeVariablesMap,
|
|
33
|
-
decodeDataSourceVariable,
|
|
34
|
-
decodeVariablesMap,
|
|
35
|
-
} from "./expression";
|
|
36
|
-
export { renderComponentTemplate } from "./component-renderer";
|
|
37
|
-
export { getIndexesWithinAncestors } from "./instance-utils";
|
|
38
|
-
export * from "./hook";
|
|
39
|
-
export { generateUtilsExport } from "./generator";
|
package/src/instance-utils.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import type { Instance, Instances } from "@webstudio-is/project-build";
|
|
2
|
-
import type { WsComponentMeta } from "./components/component-meta";
|
|
3
|
-
|
|
4
|
-
export type IndexesWithinAncestors = Map<Instance["id"], number>;
|
|
5
|
-
|
|
6
|
-
export const getIndexesWithinAncestors = (
|
|
7
|
-
metas: Map<Instance["component"], WsComponentMeta>,
|
|
8
|
-
instances: Instances,
|
|
9
|
-
rootIds: Instance["id"][]
|
|
10
|
-
) => {
|
|
11
|
-
const ancestors = new Set<Instance["component"]>();
|
|
12
|
-
for (const meta of metas.values()) {
|
|
13
|
-
if (meta.indexWithinAncestor !== undefined) {
|
|
14
|
-
ancestors.add(meta.indexWithinAncestor);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const indexes: IndexesWithinAncestors = new Map();
|
|
19
|
-
|
|
20
|
-
const traverseInstances = (
|
|
21
|
-
instances: Instances,
|
|
22
|
-
instanceId: Instance["id"],
|
|
23
|
-
latestIndexes = new Map<
|
|
24
|
-
Instance["component"],
|
|
25
|
-
Map<Instance["component"], number>
|
|
26
|
-
>()
|
|
27
|
-
) => {
|
|
28
|
-
const instance = instances.get(instanceId);
|
|
29
|
-
if (instance === undefined) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
const meta = metas.get(instance.component);
|
|
33
|
-
if (meta === undefined) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (ancestors.has(instance.component)) {
|
|
38
|
-
latestIndexes = new Map(latestIndexes);
|
|
39
|
-
latestIndexes.set(instance.component, new Map());
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (meta.indexWithinAncestor !== undefined) {
|
|
43
|
-
const ancestorIndexes = latestIndexes.get(meta.indexWithinAncestor);
|
|
44
|
-
if (ancestorIndexes !== undefined) {
|
|
45
|
-
let index = ancestorIndexes.get(instance.component) ?? -1;
|
|
46
|
-
index += 1;
|
|
47
|
-
ancestorIndexes.set(instance.component, index);
|
|
48
|
-
indexes.set(instance.id, index);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
for (const child of instance.children) {
|
|
53
|
-
if (child.type === "id") {
|
|
54
|
-
traverseInstances(instances, child.value, latestIndexes);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const latestIndexes = new Map();
|
|
60
|
-
for (const instanceId of rootIds) {
|
|
61
|
-
traverseInstances(instances, instanceId, latestIndexes);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return indexes;
|
|
65
|
-
};
|