@webstudio-is/react-sdk 0.60.0 → 0.61.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 (83) hide show
  1. package/lib/cjs/components/blockquote.ws.js +36 -48
  2. package/lib/cjs/components/body.ws.js +20 -17
  3. package/lib/cjs/components/button.ws.js +1 -1
  4. package/lib/cjs/components/code.ws.js +20 -28
  5. package/lib/cjs/components/component-meta.js +2 -1
  6. package/lib/cjs/components/form.ws.js +14 -7
  7. package/lib/cjs/components/heading.ws.js +1 -1
  8. package/lib/cjs/components/image.ws.js +8 -9
  9. package/lib/cjs/components/italic.ws.js +5 -5
  10. package/lib/cjs/components/link-block.ws.js +5 -5
  11. package/lib/cjs/components/link.ws.js +9 -10
  12. package/lib/cjs/components/list-item.ws.js +1 -1
  13. package/lib/cjs/components/list.ws.js +22 -22
  14. package/lib/cjs/components/paragraph.ws.js +1 -1
  15. package/lib/cjs/components/separator.ws.js +20 -20
  16. package/lib/cjs/components/text-block.ws.js +6 -7
  17. package/lib/cjs/css/css.js +6 -9
  18. package/lib/cjs/css/normalize.js +166 -185
  19. package/lib/cjs/css/presets.js +14 -34
  20. package/lib/cjs/css/style-rules.js +17 -0
  21. package/lib/cjs/embed-template.js +160 -0
  22. package/lib/cjs/index.js +1 -0
  23. package/lib/components/blockquote.ws.js +36 -48
  24. package/lib/components/body.ws.js +20 -17
  25. package/lib/components/button.ws.js +1 -1
  26. package/lib/components/code.ws.js +20 -28
  27. package/lib/components/component-meta.js +2 -1
  28. package/lib/components/form.ws.js +14 -7
  29. package/lib/components/heading.ws.js +1 -1
  30. package/lib/components/image.ws.js +8 -9
  31. package/lib/components/italic.ws.js +5 -5
  32. package/lib/components/link-block.ws.js +5 -5
  33. package/lib/components/link.ws.js +9 -10
  34. package/lib/components/list-item.ws.js +1 -1
  35. package/lib/components/list.ws.js +22 -22
  36. package/lib/components/paragraph.ws.js +1 -1
  37. package/lib/components/separator.ws.js +20 -20
  38. package/lib/components/text-block.ws.js +6 -7
  39. package/lib/css/css.js +8 -11
  40. package/lib/css/normalize.js +166 -185
  41. package/lib/css/presets.js +14 -34
  42. package/lib/css/style-rules.js +17 -0
  43. package/lib/embed-template.js +140 -0
  44. package/lib/index.js +1 -0
  45. package/lib/types/components/box.stories.d.ts +2 -2
  46. package/lib/types/components/component-meta.d.ts +20 -5
  47. package/lib/types/components/components-utils.d.ts +1 -1
  48. package/lib/types/css/normalize.d.ts +8786 -2286
  49. package/lib/types/css/presets.d.ts +2 -38
  50. package/lib/types/css/style-rules.d.ts +11 -9
  51. package/lib/types/embed-template.d.ts +1725 -0
  52. package/lib/types/embed-template.test.d.ts +1 -0
  53. package/lib/types/index.d.ts +1 -0
  54. package/package.json +14 -13
  55. package/src/components/blockquote.ws.tsx +42 -52
  56. package/src/components/body.ws.tsx +26 -23
  57. package/src/components/bold.ws.tsx +6 -3
  58. package/src/components/box.ws.ts +6 -3
  59. package/src/components/button.ws.tsx +7 -4
  60. package/src/components/code.ws.tsx +26 -32
  61. package/src/components/component-meta.ts +5 -3
  62. package/src/components/form.ws.tsx +19 -9
  63. package/src/components/heading.ws.tsx +7 -4
  64. package/src/components/image.ws.tsx +14 -12
  65. package/src/components/input.ws.tsx +6 -3
  66. package/src/components/italic.ws.tsx +11 -8
  67. package/src/components/link-block.ws.tsx +11 -8
  68. package/src/components/link.ws.tsx +15 -13
  69. package/src/components/list-item.ws.tsx +7 -4
  70. package/src/components/list.ws.tsx +28 -25
  71. package/src/components/paragraph.ws.tsx +7 -4
  72. package/src/components/separator.ws.tsx +26 -25
  73. package/src/components/span.ws.tsx +6 -3
  74. package/src/components/subscript.ws.tsx +6 -3
  75. package/src/components/superscript.ws.tsx +6 -3
  76. package/src/components/text-block.ws.tsx +12 -11
  77. package/src/css/css.ts +8 -11
  78. package/src/css/normalize.ts +165 -188
  79. package/src/css/presets.ts +15 -37
  80. package/src/css/style-rules.ts +24 -0
  81. package/src/embed-template.test.ts +210 -0
  82. package/src/embed-template.ts +187 -0
  83. package/src/index.ts +1 -0
@@ -0,0 +1,210 @@
1
+ import { expect, test } from "@jest/globals";
2
+ import { generateDataFromEmbedTemplate } from "./embed-template";
3
+
4
+ const expectString = expect.any(String) as unknown as string;
5
+
6
+ const defaultBreakpointId = "base";
7
+
8
+ test("generate data for embedding from instances and text", () => {
9
+ expect(
10
+ generateDataFromEmbedTemplate(
11
+ [
12
+ { type: "text", value: "hello" },
13
+ {
14
+ type: "instance",
15
+ component: "Box1",
16
+ children: [
17
+ { type: "instance", component: "Box2", children: [] },
18
+ { type: "text", value: "world" },
19
+ ],
20
+ },
21
+ ],
22
+ defaultBreakpointId
23
+ )
24
+ ).toEqual({
25
+ children: [
26
+ { type: "text", value: "hello" },
27
+ { type: "id", value: expectString },
28
+ ],
29
+ instances: [
30
+ {
31
+ type: "instance",
32
+ id: expectString,
33
+ component: "Box1",
34
+ children: [
35
+ { type: "id", value: expectString },
36
+ { type: "text", value: "world" },
37
+ ],
38
+ },
39
+ {
40
+ type: "instance",
41
+ id: expectString,
42
+ component: "Box2",
43
+ children: [],
44
+ },
45
+ ],
46
+ props: [],
47
+ styleSourceSelections: [],
48
+ styleSources: [],
49
+ styles: [],
50
+ });
51
+ });
52
+
53
+ test("generate data for embedding from props", () => {
54
+ expect(
55
+ generateDataFromEmbedTemplate(
56
+ [
57
+ {
58
+ type: "instance",
59
+ component: "Box1",
60
+ props: [
61
+ { type: "string", name: "data-prop1", value: "value1" },
62
+ { type: "string", name: "data-prop2", value: "value2" },
63
+ ],
64
+ children: [
65
+ {
66
+ type: "instance",
67
+ component: "Box2",
68
+ props: [{ type: "string", name: "data-prop3", value: "value3" }],
69
+ children: [],
70
+ },
71
+ ],
72
+ },
73
+ ],
74
+ defaultBreakpointId
75
+ )
76
+ ).toEqual({
77
+ children: [{ type: "id", value: expectString }],
78
+ instances: [
79
+ {
80
+ type: "instance",
81
+ id: expectString,
82
+ component: "Box1",
83
+ children: [{ type: "id", value: expectString }],
84
+ },
85
+ {
86
+ type: "instance",
87
+ id: expectString,
88
+ component: "Box2",
89
+ children: [],
90
+ },
91
+ ],
92
+ props: [
93
+ {
94
+ type: "string",
95
+ id: expectString,
96
+ instanceId: expectString,
97
+ name: "data-prop1",
98
+ value: "value1",
99
+ },
100
+ {
101
+ type: "string",
102
+ id: expectString,
103
+ instanceId: expectString,
104
+ name: "data-prop2",
105
+ value: "value2",
106
+ },
107
+ {
108
+ type: "string",
109
+ id: expectString,
110
+ instanceId: expectString,
111
+ name: "data-prop3",
112
+ value: "value3",
113
+ },
114
+ ],
115
+ styleSourceSelections: [],
116
+ styleSources: [],
117
+ styles: [],
118
+ });
119
+ });
120
+
121
+ test("generate data for embedding from styles", () => {
122
+ expect(
123
+ generateDataFromEmbedTemplate(
124
+ [
125
+ {
126
+ type: "instance",
127
+ component: "Box1",
128
+ styles: [
129
+ { property: "width", value: { type: "keyword", value: "auto" } },
130
+ { property: "height", value: { type: "keyword", value: "auto" } },
131
+ ],
132
+ children: [
133
+ {
134
+ type: "instance",
135
+ component: "Box2",
136
+ styles: [
137
+ {
138
+ property: "color",
139
+ value: { type: "keyword", value: "black" },
140
+ },
141
+ ],
142
+ children: [],
143
+ },
144
+ ],
145
+ },
146
+ ],
147
+ defaultBreakpointId
148
+ )
149
+ ).toEqual({
150
+ children: [{ type: "id", value: expectString }],
151
+ instances: [
152
+ {
153
+ type: "instance",
154
+ id: expectString,
155
+ component: "Box1",
156
+ children: [{ type: "id", value: expectString }],
157
+ },
158
+ {
159
+ type: "instance",
160
+ id: expectString,
161
+ component: "Box2",
162
+ children: [],
163
+ },
164
+ ],
165
+ props: [],
166
+ styleSourceSelections: [
167
+ {
168
+ instanceId: expectString,
169
+ values: [expectString],
170
+ },
171
+ {
172
+ instanceId: expectString,
173
+ values: [expectString],
174
+ },
175
+ ],
176
+ styleSources: [
177
+ {
178
+ type: "local",
179
+ id: expectString,
180
+ },
181
+ {
182
+ type: "local",
183
+ id: expectString,
184
+ },
185
+ ],
186
+ styles: [
187
+ {
188
+ breakpointId: "base",
189
+ styleSourceId: expectString,
190
+ state: undefined,
191
+ property: "width",
192
+ value: { type: "keyword", value: "auto" },
193
+ },
194
+ {
195
+ breakpointId: "base",
196
+ styleSourceId: expectString,
197
+ state: undefined,
198
+ property: "height",
199
+ value: { type: "keyword", value: "auto" },
200
+ },
201
+ {
202
+ breakpointId: "base",
203
+ styleSourceId: expectString,
204
+ state: undefined,
205
+ property: "color",
206
+ value: { type: "keyword", value: "black" },
207
+ },
208
+ ],
209
+ });
210
+ });
@@ -0,0 +1,187 @@
1
+ import { z } from "zod";
2
+ import { nanoid } from "nanoid";
3
+ import {
4
+ type Instance,
5
+ type InstancesList,
6
+ PropsList,
7
+ StyleSourceSelectionsList,
8
+ StyleSourcesList,
9
+ StylesList,
10
+ Breakpoint,
11
+ } from "@webstudio-is/project-build";
12
+ import { StyleValue, type StyleProperty } from "@webstudio-is/css-data";
13
+
14
+ const EmbedTemplateText = z.object({
15
+ type: z.literal("text"),
16
+ value: z.string(),
17
+ });
18
+
19
+ type EmbedTemplateText = z.infer<typeof EmbedTemplateText>;
20
+
21
+ const EmbedTemplateProp = z.union([
22
+ z.object({
23
+ type: z.literal("number"),
24
+ name: z.string(),
25
+ value: z.number(),
26
+ }),
27
+ z.object({
28
+ type: z.literal("string"),
29
+ name: z.string(),
30
+ value: z.string(),
31
+ }),
32
+ z.object({
33
+ type: z.literal("boolean"),
34
+ name: z.string(),
35
+ value: z.boolean(),
36
+ }),
37
+ z.object({
38
+ type: z.literal("string[]"),
39
+ name: z.string(),
40
+ value: z.array(z.string()),
41
+ }),
42
+ ]);
43
+
44
+ type EmbedTemplateProp = z.infer<typeof EmbedTemplateProp>;
45
+
46
+ export const EmbedTemplateStyleDecl = z.object({
47
+ state: z.optional(z.string()),
48
+ property: z.string() as z.ZodType<StyleProperty>,
49
+ value: StyleValue,
50
+ });
51
+
52
+ export type EmbedTemplateStyleDecl = z.infer<typeof EmbedTemplateStyleDecl>;
53
+
54
+ export type EmbedTemplateInstance = {
55
+ type: "instance";
56
+ component: string;
57
+ props?: EmbedTemplateProp[];
58
+ styles?: EmbedTemplateStyleDecl[];
59
+ children: Array<EmbedTemplateInstance | EmbedTemplateText>;
60
+ };
61
+
62
+ export const EmbedTemplateInstance: z.ZodType<EmbedTemplateInstance> = z.lazy(
63
+ () =>
64
+ z.object({
65
+ type: z.literal("instance"),
66
+ component: z.string(),
67
+ props: z.optional(z.array(EmbedTemplateProp)),
68
+ styles: z.optional(z.array(EmbedTemplateStyleDecl)),
69
+ children: WsEmbedTemplate,
70
+ })
71
+ );
72
+
73
+ export const WsEmbedTemplate = z.lazy(() =>
74
+ z.array(z.union([EmbedTemplateInstance, EmbedTemplateText]))
75
+ );
76
+
77
+ export type WsEmbedTemplate = z.infer<typeof WsEmbedTemplate>;
78
+
79
+ const createInstancesFromTemplate = (
80
+ treeTemplate: WsEmbedTemplate,
81
+ instances: InstancesList,
82
+ props: PropsList,
83
+ styleSourceSelections: StyleSourceSelectionsList,
84
+ styleSources: StyleSourcesList,
85
+ styles: StylesList,
86
+ defaultBreakpointId: Breakpoint["id"]
87
+ ) => {
88
+ const parentChildren: Instance["children"] = [];
89
+ for (const item of treeTemplate) {
90
+ if (item.type === "instance") {
91
+ const instanceId = nanoid();
92
+
93
+ // populate props
94
+ if (item.props) {
95
+ for (const prop of item.props) {
96
+ props.push({
97
+ id: nanoid(),
98
+ instanceId,
99
+ ...prop,
100
+ });
101
+ }
102
+ }
103
+
104
+ // populate styles
105
+ if (item.styles) {
106
+ const styleSourceId = nanoid();
107
+ styleSources.push({
108
+ type: "local",
109
+ id: styleSourceId,
110
+ });
111
+ styleSourceSelections.push({
112
+ instanceId,
113
+ values: [styleSourceId],
114
+ });
115
+ for (const styleDecl of item.styles) {
116
+ styles.push({
117
+ breakpointId: defaultBreakpointId,
118
+ styleSourceId,
119
+ state: styleDecl.state,
120
+ property: styleDecl.property,
121
+ value: styleDecl.value,
122
+ });
123
+ }
124
+ }
125
+
126
+ // populate instances
127
+ const instance: Instance = {
128
+ type: "instance",
129
+ id: instanceId,
130
+ component: item.component,
131
+ children: [],
132
+ };
133
+ instances.push(instance);
134
+ // traverse children after to preserve top down order
135
+ instance.children = createInstancesFromTemplate(
136
+ item.children,
137
+ instances,
138
+ props,
139
+ styleSourceSelections,
140
+ styleSources,
141
+ styles,
142
+ defaultBreakpointId
143
+ );
144
+ parentChildren.push({
145
+ type: "id",
146
+ value: instanceId,
147
+ });
148
+ }
149
+
150
+ if (item.type === "text") {
151
+ parentChildren.push({
152
+ type: "text",
153
+ value: item.value,
154
+ });
155
+ }
156
+ }
157
+ return parentChildren;
158
+ };
159
+
160
+ export const generateDataFromEmbedTemplate = (
161
+ treeTemplate: WsEmbedTemplate,
162
+ defaultBreakpointId: Breakpoint["id"]
163
+ ) => {
164
+ const instances: InstancesList = [];
165
+ const props: PropsList = [];
166
+ const styleSourceSelections: StyleSourceSelectionsList = [];
167
+ const styleSources: StyleSourcesList = [];
168
+ const styles: StylesList = [];
169
+
170
+ const children = createInstancesFromTemplate(
171
+ treeTemplate,
172
+ instances,
173
+ props,
174
+ styleSourceSelections,
175
+ styleSources,
176
+ styles,
177
+ defaultBreakpointId
178
+ );
179
+ return {
180
+ children,
181
+ instances,
182
+ props,
183
+ styleSourceSelections,
184
+ styleSources,
185
+ styles,
186
+ };
187
+ };
package/src/index.ts CHANGED
@@ -16,3 +16,4 @@ export {
16
16
  type ComponentState,
17
17
  componentCategories,
18
18
  } from "./components/component-meta";
19
+ export * from "./embed-template";