@webstudio-is/react-sdk 0.90.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.
Files changed (108) hide show
  1. package/lib/app/index.js +1 -0
  2. package/lib/app/root.js +2 -4
  3. package/lib/component-renderer.js +3 -5
  4. package/lib/components/component-meta.js +6 -11
  5. package/lib/components/components-utils.js +1 -0
  6. package/lib/context.js +2 -4
  7. package/lib/css/css.js +4 -9
  8. package/lib/css/global-rules.js +3 -5
  9. package/lib/css/index.js +1 -0
  10. package/lib/css/normalize-type-check.js +1 -0
  11. package/lib/css/normalize.js +48 -96
  12. package/lib/css/presets.js +3 -6
  13. package/lib/css/style-rules.js +3 -6
  14. package/{src/css/style-rules.test.ts → lib/css/style-rules.test.js} +23 -28
  15. package/lib/embed-template.js +7 -22
  16. package/{src/embed-template.test.ts → lib/embed-template.test.js} +165 -176
  17. package/lib/expression.js +11 -22
  18. package/{src/expression.test.ts → lib/expression.test.js} +55 -83
  19. package/lib/generator.js +2 -4
  20. package/{src/generator.test.ts → lib/generator.test.js} +28 -31
  21. package/lib/hook.js +2 -4
  22. package/{src/hook.test.ts → lib/hook.test.js} +4 -4
  23. package/lib/index.js +9 -31
  24. package/lib/instance-utils.js +2 -4
  25. package/{src/instance-utils.test.ts → lib/instance-utils.test.js} +19 -43
  26. package/lib/prop-meta.js +150 -0
  27. package/lib/props.js +8 -16
  28. package/{src/props.test.ts → lib/props.test.js} +39 -68
  29. package/lib/pubsub/create.js +2 -4
  30. package/lib/pubsub/index.js +1 -0
  31. package/lib/pubsub/raf-queue.js +2 -4
  32. package/lib/tree/create-elements-tree.js +2 -4
  33. package/lib/tree/index.js +1 -0
  34. package/lib/tree/root.js +2 -5
  35. package/lib/tree/webstudio-component.js +10 -20
  36. package/lib/types/component-renderer.d.ts +1 -1
  37. package/lib/types/components/component-meta.d.ts +526 -526
  38. package/lib/types/context.d.ts +1 -2
  39. package/lib/types/css/css.d.ts +22 -23
  40. package/lib/types/css/global-rules.d.ts +19 -19
  41. package/lib/types/css/normalize.d.ts +2444 -2444
  42. package/lib/types/css/style-rules.d.ts +2 -2
  43. package/lib/types/embed-template.d.ts +648 -648
  44. package/lib/types/generator.d.ts +1 -1
  45. package/lib/types/hook.d.ts +3 -3
  46. package/lib/types/index.d.ts +1 -0
  47. package/lib/types/instance-utils.d.ts +3 -3
  48. package/lib/types/prop-meta.d.ts +396 -0
  49. package/lib/types/props.d.ts +52 -53
  50. package/lib/types/tree/create-elements-tree.d.ts +3 -4
  51. package/lib/types/tree/root.d.ts +8 -8
  52. package/lib/types/tree/webstudio-component.d.ts +1 -1
  53. package/package.json +14 -22
  54. package/lib/cjs/app/index.js +0 -18
  55. package/lib/cjs/app/root.js +0 -40
  56. package/lib/cjs/component-renderer.js +0 -143
  57. package/lib/cjs/components/component-meta.js +0 -87
  58. package/lib/cjs/components/components-utils.js +0 -17
  59. package/lib/cjs/context.js +0 -43
  60. package/lib/cjs/css/css.js +0 -84
  61. package/lib/cjs/css/global-rules.js +0 -37
  62. package/lib/cjs/css/index.js +0 -20
  63. package/lib/cjs/css/normalize-type-check.js +0 -26
  64. package/lib/cjs/css/normalize.js +0 -349
  65. package/lib/cjs/css/presets.js +0 -48
  66. package/lib/cjs/css/style-rules.js +0 -86
  67. package/lib/cjs/embed-template.js +0 -368
  68. package/lib/cjs/expression.js +0 -371
  69. package/lib/cjs/generator.js +0 -128
  70. package/lib/cjs/hook.js +0 -34
  71. package/lib/cjs/index.js +0 -59
  72. package/lib/cjs/instance-utils.js +0 -65
  73. package/lib/cjs/package.json +0 -1
  74. package/lib/cjs/props.js +0 -204
  75. package/lib/cjs/pubsub/create.js +0 -78
  76. package/lib/cjs/pubsub/index.js +0 -18
  77. package/lib/cjs/pubsub/raf-queue.js +0 -42
  78. package/lib/cjs/tree/create-elements-tree.js +0 -152
  79. package/lib/cjs/tree/index.js +0 -20
  80. package/lib/cjs/tree/root.js +0 -100
  81. package/lib/cjs/tree/webstudio-component.js +0 -91
  82. package/src/app/index.ts +0 -1
  83. package/src/app/root.tsx +0 -25
  84. package/src/component-renderer.tsx +0 -146
  85. package/src/components/component-meta.ts +0 -86
  86. package/src/components/components-utils.ts +0 -13
  87. package/src/context.tsx +0 -73
  88. package/src/css/css.ts +0 -88
  89. package/src/css/global-rules.ts +0 -26
  90. package/src/css/index.ts +0 -3
  91. package/src/css/normalize-type-check.ts +0 -13
  92. package/src/css/normalize.ts +0 -507
  93. package/src/css/presets.ts +0 -27
  94. package/src/css/style-rules.ts +0 -101
  95. package/src/embed-template.ts +0 -438
  96. package/src/expression.ts +0 -401
  97. package/src/generator.ts +0 -147
  98. package/src/hook.ts +0 -52
  99. package/src/index.ts +0 -39
  100. package/src/instance-utils.ts +0 -65
  101. package/src/props.ts +0 -231
  102. package/src/pubsub/create.ts +0 -77
  103. package/src/pubsub/index.ts +0 -1
  104. package/src/pubsub/raf-queue.ts +0 -25
  105. package/src/tree/create-elements-tree.tsx +0 -186
  106. package/src/tree/index.ts +0 -3
  107. package/src/tree/root.ts +0 -131
  108. package/src/tree/webstudio-component.tsx +0 -97
@@ -1,438 +0,0 @@
1
- import { z } from "zod";
2
- import { nanoid } from "nanoid";
3
- import { titleCase } from "title-case";
4
- import { noCase } from "no-case";
5
- import {
6
- Instance,
7
- type InstancesList,
8
- PropsList,
9
- StyleSourceSelectionsList,
10
- StyleSourcesList,
11
- StylesList,
12
- Breakpoint,
13
- DataSource,
14
- } from "@webstudio-is/project-build";
15
- import { StyleValue, type StyleProperty } from "@webstudio-is/css-data";
16
- import type { Simplify } from "type-fest";
17
- import { encodeDataSourceVariable, validateExpression } from "./expression";
18
- import type { WsComponentMeta } from "./components/component-meta";
19
-
20
- const EmbedTemplateText = z.object({
21
- type: z.literal("text"),
22
- value: z.string(),
23
- });
24
-
25
- type EmbedTemplateText = z.infer<typeof EmbedTemplateText>;
26
-
27
- const EmbedTemplateDataSource = z.union([
28
- z.object({
29
- type: z.literal("variable"),
30
- initialValue: z.union([
31
- z.string(),
32
- z.number(),
33
- z.boolean(),
34
- z.array(z.string()),
35
- ]),
36
- }),
37
- z.object({
38
- type: z.literal("expression"),
39
- code: z.string(),
40
- }),
41
- ]);
42
-
43
- type EmbedTemplateDataSource = z.infer<typeof EmbedTemplateDataSource>;
44
-
45
- const EmbedTemplateProp = z.union([
46
- z.object({
47
- type: z.literal("dataSource"),
48
- name: z.string(),
49
- dataSourceName: z.string(),
50
- }),
51
- z.object({
52
- type: z.literal("number"),
53
- name: z.string(),
54
- value: z.number(),
55
- }),
56
- z.object({
57
- type: z.literal("string"),
58
- name: z.string(),
59
- value: z.string(),
60
- }),
61
- z.object({
62
- type: z.literal("boolean"),
63
- name: z.string(),
64
- value: z.boolean(),
65
- }),
66
- z.object({
67
- type: z.literal("string[]"),
68
- name: z.string(),
69
- value: z.array(z.string()),
70
- }),
71
- z.object({
72
- type: z.literal("action"),
73
- name: z.string(),
74
- value: z.array(
75
- z.object({
76
- type: z.literal("execute"),
77
- args: z.optional(z.array(z.string())),
78
- code: z.string(),
79
- })
80
- ),
81
- }),
82
- ]);
83
-
84
- type EmbedTemplateProp = z.infer<typeof EmbedTemplateProp>;
85
-
86
- const EmbedTemplateStyleDeclRaw = z.object({
87
- // State selector, e.g. :hover
88
- state: z.optional(z.string()),
89
- property: z.string(),
90
- value: StyleValue,
91
- });
92
-
93
- export type EmbedTemplateStyleDecl = Simplify<
94
- Omit<z.infer<typeof EmbedTemplateStyleDeclRaw>, "property"> & {
95
- property: StyleProperty;
96
- }
97
- >;
98
-
99
- export const EmbedTemplateStyleDecl =
100
- EmbedTemplateStyleDeclRaw as z.ZodType<EmbedTemplateStyleDecl>;
101
-
102
- export type EmbedTemplateInstance = {
103
- type: "instance";
104
- component: string;
105
- label?: string;
106
- dataSources?: Record<string, EmbedTemplateDataSource>;
107
- props?: EmbedTemplateProp[];
108
- tokens?: string[];
109
- styles?: EmbedTemplateStyleDecl[];
110
- children: Array<EmbedTemplateInstance | EmbedTemplateText>;
111
- };
112
-
113
- export const EmbedTemplateInstance: z.ZodType<EmbedTemplateInstance> = z.lazy(
114
- () =>
115
- z.object({
116
- type: z.literal("instance"),
117
- component: z.string(),
118
- label: z.optional(z.string()),
119
- dataSources: z.optional(z.record(z.string(), EmbedTemplateDataSource)),
120
- props: z.optional(z.array(EmbedTemplateProp)),
121
- tokens: z.optional(z.array(z.string())),
122
- styles: z.optional(z.array(EmbedTemplateStyleDecl)),
123
- children: WsEmbedTemplate,
124
- })
125
- );
126
-
127
- export const WsEmbedTemplate = z.lazy(() =>
128
- z.array(z.union([EmbedTemplateInstance, EmbedTemplateText]))
129
- );
130
-
131
- export type WsEmbedTemplate = z.infer<typeof WsEmbedTemplate>;
132
-
133
- const getDataSourceValue = (
134
- value: Extract<EmbedTemplateDataSource, { type: "variable" }>["initialValue"]
135
- ): Extract<DataSource, { type: "variable" }>["value"] => {
136
- if (typeof value === "string") {
137
- return { type: "string", value };
138
- }
139
- if (typeof value === "number") {
140
- return { type: "number", value };
141
- }
142
- if (typeof value === "boolean") {
143
- return { type: "boolean", value };
144
- }
145
- if (Array.isArray(value)) {
146
- return { type: "string[]", value };
147
- }
148
- value satisfies never;
149
- throw Error("Impossible case");
150
- };
151
-
152
- const createInstancesFromTemplate = (
153
- treeTemplate: WsEmbedTemplate,
154
- instances: InstancesList,
155
- props: PropsList,
156
- dataSourceByRef: Map<string, DataSource>,
157
- styleSourceSelections: StyleSourceSelectionsList,
158
- styleSources: StyleSourcesList,
159
- styles: StylesList,
160
- metas: Map<Instance["component"], WsComponentMeta>,
161
- defaultBreakpointId: Breakpoint["id"]
162
- ) => {
163
- const parentChildren: Instance["children"] = [];
164
- for (const item of treeTemplate) {
165
- if (item.type === "instance") {
166
- const instanceId = nanoid();
167
-
168
- if (item.dataSources) {
169
- for (const [name, dataSource] of Object.entries(item.dataSources)) {
170
- if (dataSourceByRef.has(name)) {
171
- throw Error(`${name} data source already defined`);
172
- }
173
- if (dataSource.type === "variable") {
174
- dataSourceByRef.set(name, {
175
- type: "variable",
176
- id: nanoid(),
177
- scopeInstanceId: instanceId,
178
- name,
179
- value: getDataSourceValue(dataSource.initialValue),
180
- });
181
- }
182
- if (dataSource.type === "expression") {
183
- dataSourceByRef.set(name, {
184
- type: "expression",
185
- id: nanoid(),
186
- scopeInstanceId: instanceId,
187
- name,
188
- // replace all references with variable names
189
- code: validateExpression(dataSource.code, {
190
- transformIdentifier: (ref) => {
191
- const id = dataSourceByRef.get(ref)?.id ?? ref;
192
- return encodeDataSourceVariable(id);
193
- },
194
- }),
195
- });
196
- }
197
- }
198
- }
199
-
200
- // populate props
201
- if (item.props) {
202
- for (const prop of item.props) {
203
- const propId = nanoid();
204
- // action cannot be bound to data source
205
- if (prop.type === "action") {
206
- props.push({
207
- id: propId,
208
- instanceId,
209
- type: "action",
210
- name: prop.name,
211
- value: prop.value.map((value) => {
212
- const args = value.args ?? [];
213
- return {
214
- type: "execute",
215
- args,
216
- // replace all references with variable names
217
- code: validateExpression(value.code, {
218
- effectful: true,
219
- transformIdentifier: (ref) => {
220
- // bypass arguments without changes
221
- if (args.includes(ref)) {
222
- return ref;
223
- }
224
- const id = dataSourceByRef.get(ref)?.id ?? ref;
225
- return encodeDataSourceVariable(id);
226
- },
227
- }),
228
- };
229
- }),
230
- });
231
- continue;
232
- }
233
- if (prop.type === "dataSource") {
234
- const dataSource = dataSourceByRef.get(prop.dataSourceName);
235
- if (dataSource === undefined) {
236
- throw Error(`${prop.dataSourceName} data source is not defined`);
237
- }
238
- props.push({
239
- id: propId,
240
- instanceId,
241
- type: "dataSource",
242
- name: prop.name,
243
- value: dataSource.id,
244
- });
245
- continue;
246
- }
247
- props.push({ id: propId, instanceId, ...prop });
248
- }
249
- }
250
-
251
- const styleSourceIds: string[] = [];
252
-
253
- // convert tokens into style sources and styles
254
- if (item.tokens) {
255
- const meta = metas.get(item.component);
256
- if (meta?.presetTokens) {
257
- for (const name of item.tokens) {
258
- const tokenValue = meta.presetTokens[name];
259
- if (tokenValue) {
260
- const styleSourceId = `${item.component}:${name}`;
261
- styleSourceIds.push(styleSourceId);
262
- styleSources.push({
263
- type: "token",
264
- id: styleSourceId,
265
- name: titleCase(noCase(name)),
266
- });
267
- for (const styleDecl of tokenValue.styles) {
268
- styles.push({
269
- breakpointId: defaultBreakpointId,
270
- styleSourceId,
271
- state: styleDecl.state,
272
- property: styleDecl.property,
273
- value: styleDecl.value,
274
- });
275
- }
276
- }
277
- }
278
- }
279
- }
280
-
281
- // populate styles
282
- if (item.styles) {
283
- const styleSourceId = nanoid();
284
- styleSources.push({
285
- type: "local",
286
- id: styleSourceId,
287
- });
288
- styleSourceIds.push(styleSourceId);
289
- for (const styleDecl of item.styles) {
290
- styles.push({
291
- breakpointId: defaultBreakpointId,
292
- styleSourceId,
293
- state: styleDecl.state,
294
- property: styleDecl.property,
295
- value: styleDecl.value,
296
- });
297
- }
298
- }
299
-
300
- if (styleSourceIds.length > 0) {
301
- styleSourceSelections.push({
302
- instanceId,
303
- values: styleSourceIds,
304
- });
305
- }
306
-
307
- // populate instances
308
- const instance: Instance = {
309
- type: "instance",
310
- id: instanceId,
311
- label: item.label,
312
- component: item.component,
313
- children: [],
314
- };
315
- instances.push(instance);
316
- // traverse children after to preserve top down order
317
- instance.children = createInstancesFromTemplate(
318
- item.children,
319
- instances,
320
- props,
321
- dataSourceByRef,
322
- styleSourceSelections,
323
- styleSources,
324
- styles,
325
- metas,
326
- defaultBreakpointId
327
- );
328
- parentChildren.push({
329
- type: "id",
330
- value: instanceId,
331
- });
332
- }
333
-
334
- if (item.type === "text") {
335
- parentChildren.push({
336
- type: "text",
337
- value: item.value,
338
- });
339
- }
340
- }
341
- return parentChildren;
342
- };
343
-
344
- export const generateDataFromEmbedTemplate = (
345
- treeTemplate: WsEmbedTemplate,
346
- metas: Map<Instance["component"], WsComponentMeta>,
347
- defaultBreakpointId: Breakpoint["id"]
348
- ) => {
349
- const instances: InstancesList = [];
350
- const props: PropsList = [];
351
- const dataSourceByRef = new Map<string, DataSource>();
352
- const styleSourceSelections: StyleSourceSelectionsList = [];
353
- const styleSources: StyleSourcesList = [];
354
- const styles: StylesList = [];
355
-
356
- const children = createInstancesFromTemplate(
357
- treeTemplate,
358
- instances,
359
- props,
360
- dataSourceByRef,
361
- styleSourceSelections,
362
- styleSources,
363
- styles,
364
- metas,
365
- defaultBreakpointId
366
- );
367
-
368
- return {
369
- children,
370
- instances,
371
- props,
372
- dataSources: Array.from(dataSourceByRef.values()),
373
- styleSourceSelections,
374
- styleSources,
375
- styles,
376
- };
377
- };
378
-
379
- export type EmbedTemplateData = ReturnType<
380
- typeof generateDataFromEmbedTemplate
381
- >;
382
-
383
- const namespaceEmbedTemplateComponents = (
384
- template: WsEmbedTemplate,
385
- namespace: string,
386
- components: Set<EmbedTemplateInstance["component"]>
387
- ): WsEmbedTemplate => {
388
- return template.map((item) => {
389
- if (item.type === "text") {
390
- return item;
391
- }
392
- if (item.type === "instance") {
393
- const prefix = components.has(item.component) ? `${namespace}:` : "";
394
- return {
395
- ...item,
396
- component: `${prefix}${item.component}`,
397
- children: namespaceEmbedTemplateComponents(
398
- item.children,
399
- namespace,
400
- components
401
- ),
402
- };
403
- }
404
- item satisfies never;
405
- throw Error("Impossible case");
406
- });
407
- };
408
-
409
- export const namespaceMeta = (
410
- meta: WsComponentMeta,
411
- namespace: string,
412
- components: Set<EmbedTemplateInstance["component"]>
413
- ) => {
414
- const newMeta = { ...meta };
415
- if (newMeta.requiredAncestors) {
416
- newMeta.requiredAncestors = newMeta.requiredAncestors.map((component) =>
417
- components.has(component) ? `${namespace}:${component}` : component
418
- );
419
- }
420
- if (newMeta.invalidAncestors) {
421
- newMeta.invalidAncestors = newMeta.invalidAncestors.map((component) =>
422
- components.has(component) ? `${namespace}:${component}` : component
423
- );
424
- }
425
- if (newMeta.indexWithinAncestor) {
426
- newMeta.indexWithinAncestor = components.has(newMeta.indexWithinAncestor)
427
- ? `${namespace}:${newMeta.indexWithinAncestor}`
428
- : newMeta.indexWithinAncestor;
429
- }
430
- if (newMeta.template) {
431
- newMeta.template = namespaceEmbedTemplateComponents(
432
- newMeta.template,
433
- namespace,
434
- components
435
- );
436
- }
437
- return newMeta;
438
- };