@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.
- 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/props.ts
DELETED
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
import { useContext, useMemo } from "react";
|
|
2
|
-
import { computed } from "nanostores";
|
|
3
|
-
import { useStore } from "@nanostores/react";
|
|
4
|
-
import type { Instance, Page, Prop, Props } from "@webstudio-is/project-build";
|
|
5
|
-
import type { Asset, Assets } from "@webstudio-is/asset-uploader";
|
|
6
|
-
import { ReactSdkContext } from "./context";
|
|
7
|
-
import { idAttribute, indexAttribute } from "./tree/webstudio-component";
|
|
8
|
-
|
|
9
|
-
export type PropsByInstanceId = Map<Instance["id"], Prop[]>;
|
|
10
|
-
|
|
11
|
-
export type Pages = Map<Page["id"], Page>;
|
|
12
|
-
|
|
13
|
-
export const getPropsByInstanceId = (props: Props) => {
|
|
14
|
-
const propsByInstanceId: PropsByInstanceId = new Map();
|
|
15
|
-
for (const prop of props.values()) {
|
|
16
|
-
let instanceProps = propsByInstanceId.get(prop.instanceId);
|
|
17
|
-
if (instanceProps === undefined) {
|
|
18
|
-
instanceProps = [];
|
|
19
|
-
propsByInstanceId.set(prop.instanceId, instanceProps);
|
|
20
|
-
}
|
|
21
|
-
instanceProps.push(prop);
|
|
22
|
-
}
|
|
23
|
-
return propsByInstanceId;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
// this utility is be used only for preview with static props
|
|
27
|
-
// so there is no need to use computed to optimize rerenders
|
|
28
|
-
export const useInstanceProps = (instanceId: Instance["id"]) => {
|
|
29
|
-
const {
|
|
30
|
-
propsByInstanceIdStore,
|
|
31
|
-
dataSourceValuesStore,
|
|
32
|
-
executeEffectfulExpression,
|
|
33
|
-
setDataSourceValues,
|
|
34
|
-
indexesWithinAncestors,
|
|
35
|
-
} = useContext(ReactSdkContext);
|
|
36
|
-
const index = indexesWithinAncestors.get(instanceId);
|
|
37
|
-
const instancePropsObjectStore = useMemo(() => {
|
|
38
|
-
return computed(
|
|
39
|
-
[propsByInstanceIdStore, dataSourceValuesStore],
|
|
40
|
-
(propsByInstanceId, dataSourceValues) => {
|
|
41
|
-
const instancePropsObject: Record<Prop["name"], unknown> = {};
|
|
42
|
-
if (index !== undefined) {
|
|
43
|
-
instancePropsObject[indexAttribute] = index.toString();
|
|
44
|
-
}
|
|
45
|
-
const instanceProps = propsByInstanceId.get(instanceId);
|
|
46
|
-
if (instanceProps === undefined) {
|
|
47
|
-
return instancePropsObject;
|
|
48
|
-
}
|
|
49
|
-
for (const prop of instanceProps) {
|
|
50
|
-
if (prop.type === "asset" || prop.type === "page") {
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
if (prop.type === "dataSource") {
|
|
54
|
-
const dataSourceId = prop.value;
|
|
55
|
-
const value = dataSourceValues.get(dataSourceId);
|
|
56
|
-
if (value !== undefined) {
|
|
57
|
-
instancePropsObject[prop.name] = value;
|
|
58
|
-
}
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
if (prop.type === "action") {
|
|
62
|
-
instancePropsObject[prop.name] = (...args: unknown[]) => {
|
|
63
|
-
for (const value of prop.value) {
|
|
64
|
-
if (value.type === "execute") {
|
|
65
|
-
const argsMap = new Map<string, unknown>();
|
|
66
|
-
for (const [i, name] of value.args.entries()) {
|
|
67
|
-
argsMap.set(name, args[i]);
|
|
68
|
-
}
|
|
69
|
-
const newValues = executeEffectfulExpression(
|
|
70
|
-
value.code,
|
|
71
|
-
argsMap,
|
|
72
|
-
dataSourceValues
|
|
73
|
-
);
|
|
74
|
-
setDataSourceValues(newValues);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
80
|
-
instancePropsObject[prop.name] = prop.value;
|
|
81
|
-
}
|
|
82
|
-
return instancePropsObject;
|
|
83
|
-
}
|
|
84
|
-
);
|
|
85
|
-
}, [
|
|
86
|
-
propsByInstanceIdStore,
|
|
87
|
-
dataSourceValuesStore,
|
|
88
|
-
instanceId,
|
|
89
|
-
executeEffectfulExpression,
|
|
90
|
-
setDataSourceValues,
|
|
91
|
-
index,
|
|
92
|
-
]);
|
|
93
|
-
const instancePropsObject = useStore(instancePropsObjectStore);
|
|
94
|
-
return instancePropsObject;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
// this utility is used for image component in both builder and preview
|
|
98
|
-
// so need to optimize rerenders with computed
|
|
99
|
-
export const usePropAsset = (instanceId: Instance["id"], name: string) => {
|
|
100
|
-
const { propsByInstanceIdStore, assetsStore } = useContext(ReactSdkContext);
|
|
101
|
-
const assetStore = useMemo(() => {
|
|
102
|
-
return computed(
|
|
103
|
-
[propsByInstanceIdStore, assetsStore],
|
|
104
|
-
(propsByInstanceId, assets) => {
|
|
105
|
-
const instanceProps = propsByInstanceId.get(instanceId);
|
|
106
|
-
if (instanceProps === undefined) {
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
for (const prop of instanceProps) {
|
|
110
|
-
if (prop.type === "asset" && prop.name === name) {
|
|
111
|
-
const assetId = prop.value;
|
|
112
|
-
return assets.get(assetId);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
);
|
|
117
|
-
}, [propsByInstanceIdStore, assetsStore, instanceId, name]);
|
|
118
|
-
const asset = useStore(assetStore);
|
|
119
|
-
return asset;
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
export const resolveUrlProp = (
|
|
123
|
-
instanceId: Instance["id"],
|
|
124
|
-
name: string,
|
|
125
|
-
{
|
|
126
|
-
props,
|
|
127
|
-
pages,
|
|
128
|
-
assets,
|
|
129
|
-
}: { props: PropsByInstanceId; pages: Pages; assets: Assets }
|
|
130
|
-
):
|
|
131
|
-
| {
|
|
132
|
-
type: "page";
|
|
133
|
-
page: Page;
|
|
134
|
-
instanceId?: Instance["id"];
|
|
135
|
-
hash?: string;
|
|
136
|
-
}
|
|
137
|
-
| { type: "asset"; asset: Asset }
|
|
138
|
-
| { type: "string"; url: string }
|
|
139
|
-
| undefined => {
|
|
140
|
-
const instanceProps = props.get(instanceId);
|
|
141
|
-
if (instanceProps === undefined) {
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
let prop = undefined;
|
|
146
|
-
|
|
147
|
-
// We had a bug that some props were duplicated https://github.com/webstudio-is/webstudio-builder/pull/2170
|
|
148
|
-
// Use the latest prop to ensure consistency with the builder settings panel.
|
|
149
|
-
for (const intanceProp of instanceProps) {
|
|
150
|
-
if (intanceProp.name !== name) {
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
prop = intanceProp;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (prop === undefined) {
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (prop.type === "page") {
|
|
161
|
-
if (typeof prop.value === "string") {
|
|
162
|
-
const page = pages.get(prop.value);
|
|
163
|
-
return page && { type: "page", page };
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const { instanceId, pageId } = prop.value;
|
|
167
|
-
|
|
168
|
-
const page = pages.get(pageId);
|
|
169
|
-
|
|
170
|
-
if (page === undefined) {
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const idProp = props.get(instanceId)?.find((prop) => prop.name === "id");
|
|
175
|
-
|
|
176
|
-
return {
|
|
177
|
-
type: "page",
|
|
178
|
-
page,
|
|
179
|
-
instanceId,
|
|
180
|
-
hash:
|
|
181
|
-
idProp === undefined || idProp.type !== "string"
|
|
182
|
-
? undefined
|
|
183
|
-
: idProp.value,
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (prop.type === "string") {
|
|
188
|
-
for (const page of pages.values()) {
|
|
189
|
-
if (page.path === prop.value) {
|
|
190
|
-
return { type: "page", page };
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return { type: "string", url: prop.value };
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (prop.type === "asset") {
|
|
197
|
-
const asset = assets.get(prop.value);
|
|
198
|
-
return asset && { type: "asset", asset };
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
return;
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
// this utility is used for link component in both builder and preview
|
|
205
|
-
// so need to optimize rerenders with computed
|
|
206
|
-
export const usePropUrl = (instanceId: Instance["id"], name: string) => {
|
|
207
|
-
const { propsByInstanceIdStore, pagesStore, assetsStore } =
|
|
208
|
-
useContext(ReactSdkContext);
|
|
209
|
-
const store = useMemo(
|
|
210
|
-
() =>
|
|
211
|
-
computed(
|
|
212
|
-
[propsByInstanceIdStore, pagesStore, assetsStore],
|
|
213
|
-
(props, pages, assets) =>
|
|
214
|
-
resolveUrlProp(instanceId, name, { props, pages, assets })
|
|
215
|
-
),
|
|
216
|
-
[propsByInstanceIdStore, pagesStore, assetsStore, instanceId, name]
|
|
217
|
-
);
|
|
218
|
-
return useStore(store);
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
export const getInstanceIdFromComponentProps = (
|
|
222
|
-
props: Record<string, unknown>
|
|
223
|
-
) => {
|
|
224
|
-
return props[idAttribute] as string;
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
export const getIndexWithinAncestorFromComponentProps = (
|
|
228
|
-
props: Record<string, unknown>
|
|
229
|
-
) => {
|
|
230
|
-
return props[indexAttribute] as string | undefined;
|
|
231
|
-
};
|
package/src/pubsub/create.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { createNanoEvents } from "nanoevents";
|
|
2
|
-
import { useCallback, useEffect, useRef } from "react";
|
|
3
|
-
import { batchUpdate } from "./raf-queue";
|
|
4
|
-
|
|
5
|
-
export const createPubsub = <PublishMap>() => {
|
|
6
|
-
type Action<Type extends keyof PublishMap> =
|
|
7
|
-
undefined extends PublishMap[Type]
|
|
8
|
-
? { type: Type; payload?: PublishMap[Type] }
|
|
9
|
-
: { type: Type; payload: PublishMap[Type] };
|
|
10
|
-
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
-
const emitter = createNanoEvents<Record<any, any>>();
|
|
13
|
-
|
|
14
|
-
if (typeof window === "object") {
|
|
15
|
-
window.addEventListener(
|
|
16
|
-
"message",
|
|
17
|
-
(event: MessageEvent) => {
|
|
18
|
-
// @todo this has no type safety built in, could be anything from any source.
|
|
19
|
-
// we could potentially maintain a list of valid event types at runtime
|
|
20
|
-
// at the very least we could add a brand property or something to our events
|
|
21
|
-
if (typeof event.data?.type === "string") {
|
|
22
|
-
// Execute all updates within a single batch to improve performance
|
|
23
|
-
batchUpdate(() => emitter.emit(event.data.type, event.data.payload));
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
false
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
/**
|
|
32
|
-
* To publish a postMessage event on the current window and parent window from the iframe.
|
|
33
|
-
*/
|
|
34
|
-
publish<Type extends keyof PublishMap>(action: Action<Type>) {
|
|
35
|
-
window.parent.postMessage(action, "*");
|
|
36
|
-
window.postMessage(action, "*");
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* To publish a postMessage event on the iframe and parent window from the parent window.
|
|
41
|
-
*/
|
|
42
|
-
usePublish() {
|
|
43
|
-
const iframeRef = useRef<HTMLIFrameElement | null>(null);
|
|
44
|
-
const publishCallback = useCallback(
|
|
45
|
-
<Type extends keyof PublishMap>(action: Action<Type>) => {
|
|
46
|
-
const element = iframeRef.current;
|
|
47
|
-
if (element?.contentWindow == null) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
element.contentWindow.postMessage(action, "*");
|
|
51
|
-
window.postMessage(action, "*");
|
|
52
|
-
},
|
|
53
|
-
[iframeRef]
|
|
54
|
-
);
|
|
55
|
-
return [publishCallback, iframeRef] as const;
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* To subscribe a message event on the current window.
|
|
60
|
-
*/
|
|
61
|
-
useSubscribe<Type extends keyof PublishMap>(
|
|
62
|
-
type: Type,
|
|
63
|
-
onAction: (payload: PublishMap[Type]) => void
|
|
64
|
-
) {
|
|
65
|
-
useEffect(() => {
|
|
66
|
-
return emitter.on(type, onAction);
|
|
67
|
-
}, [type, onAction]);
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
subscribe<Type extends keyof PublishMap>(
|
|
71
|
-
type: Type,
|
|
72
|
-
onAction: (payload: PublishMap[Type]) => void
|
|
73
|
-
) {
|
|
74
|
-
return emitter.on(type, onAction);
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
};
|
package/src/pubsub/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./create";
|
package/src/pubsub/raf-queue.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
type Task = () => void;
|
|
2
|
-
|
|
3
|
-
let handle: ReturnType<typeof requestAnimationFrame> | undefined;
|
|
4
|
-
let updateQueue: Task[] = [];
|
|
5
|
-
|
|
6
|
-
const processUpdates = (updates: Task[]) => {
|
|
7
|
-
for (const update of updates) {
|
|
8
|
-
update();
|
|
9
|
-
}
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export const batchUpdate = (update: () => void) => {
|
|
13
|
-
updateQueue.push(update);
|
|
14
|
-
|
|
15
|
-
if (handle !== undefined) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
handle = requestAnimationFrame(() => {
|
|
20
|
-
const updates = updateQueue;
|
|
21
|
-
updateQueue = [];
|
|
22
|
-
handle = undefined;
|
|
23
|
-
processUpdates(updates);
|
|
24
|
-
});
|
|
25
|
-
};
|
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Fragment,
|
|
3
|
-
type ForwardRefExoticComponent,
|
|
4
|
-
type RefAttributes,
|
|
5
|
-
type ReactNode,
|
|
6
|
-
} from "react";
|
|
7
|
-
import type { ReadableAtom } from "nanostores";
|
|
8
|
-
import type { Assets } from "@webstudio-is/asset-uploader";
|
|
9
|
-
import type { Instance, Instances } from "@webstudio-is/project-build";
|
|
10
|
-
import type { Components } from "../components/components-utils";
|
|
11
|
-
import {
|
|
12
|
-
type Params,
|
|
13
|
-
type DataSourceValues,
|
|
14
|
-
ReactSdkContext,
|
|
15
|
-
} from "../context";
|
|
16
|
-
import type { Pages, PropsByInstanceId } from "../props";
|
|
17
|
-
import type { WebstudioComponentProps } from "./webstudio-component";
|
|
18
|
-
import type { IndexesWithinAncestors } from "../instance-utils";
|
|
19
|
-
|
|
20
|
-
type InstanceSelector = Instance["id"][];
|
|
21
|
-
|
|
22
|
-
export const createElementsTree = ({
|
|
23
|
-
renderer,
|
|
24
|
-
imageBaseUrl,
|
|
25
|
-
assetBaseUrl,
|
|
26
|
-
instances,
|
|
27
|
-
rootInstanceId,
|
|
28
|
-
propsByInstanceIdStore,
|
|
29
|
-
assetsStore,
|
|
30
|
-
pagesStore,
|
|
31
|
-
dataSourceValuesStore,
|
|
32
|
-
executeEffectfulExpression,
|
|
33
|
-
onDataSourceUpdate,
|
|
34
|
-
indexesWithinAncestors,
|
|
35
|
-
Component,
|
|
36
|
-
components,
|
|
37
|
-
scripts,
|
|
38
|
-
}: Params & {
|
|
39
|
-
instances: Instances;
|
|
40
|
-
rootInstanceId: Instance["id"];
|
|
41
|
-
propsByInstanceIdStore: ReadableAtom<PropsByInstanceId>;
|
|
42
|
-
assetsStore: ReadableAtom<Assets>;
|
|
43
|
-
pagesStore: ReadableAtom<Pages>;
|
|
44
|
-
executeEffectfulExpression: (
|
|
45
|
-
expression: string,
|
|
46
|
-
args: DataSourceValues,
|
|
47
|
-
values: DataSourceValues
|
|
48
|
-
) => DataSourceValues;
|
|
49
|
-
dataSourceValuesStore: ReadableAtom<DataSourceValues>;
|
|
50
|
-
onDataSourceUpdate: (newValues: DataSourceValues) => void;
|
|
51
|
-
indexesWithinAncestors: IndexesWithinAncestors;
|
|
52
|
-
|
|
53
|
-
Component: ForwardRefExoticComponent<
|
|
54
|
-
WebstudioComponentProps & RefAttributes<HTMLElement>
|
|
55
|
-
>;
|
|
56
|
-
components: Components;
|
|
57
|
-
scripts?: ReactNode;
|
|
58
|
-
}) => {
|
|
59
|
-
const rootInstance = instances.get(rootInstanceId);
|
|
60
|
-
if (rootInstance === undefined) {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const rootInstanceSelector = [rootInstanceId];
|
|
65
|
-
const children = createInstanceChildrenElements({
|
|
66
|
-
instances,
|
|
67
|
-
instanceSelector: rootInstanceSelector,
|
|
68
|
-
Component,
|
|
69
|
-
children: rootInstance.children,
|
|
70
|
-
components,
|
|
71
|
-
});
|
|
72
|
-
const root = createInstanceElement({
|
|
73
|
-
Component,
|
|
74
|
-
instance: rootInstance,
|
|
75
|
-
instanceSelector: rootInstanceSelector,
|
|
76
|
-
children: [
|
|
77
|
-
<Fragment key="children">
|
|
78
|
-
{children}
|
|
79
|
-
{scripts}
|
|
80
|
-
</Fragment>,
|
|
81
|
-
],
|
|
82
|
-
components,
|
|
83
|
-
});
|
|
84
|
-
return (
|
|
85
|
-
<ReactSdkContext.Provider
|
|
86
|
-
value={{
|
|
87
|
-
propsByInstanceIdStore,
|
|
88
|
-
assetsStore,
|
|
89
|
-
pagesStore,
|
|
90
|
-
dataSourceValuesStore,
|
|
91
|
-
renderer,
|
|
92
|
-
imageBaseUrl,
|
|
93
|
-
assetBaseUrl,
|
|
94
|
-
indexesWithinAncestors,
|
|
95
|
-
executeEffectfulExpression,
|
|
96
|
-
setDataSourceValues: onDataSourceUpdate,
|
|
97
|
-
setBoundDataSourceValue: (instanceId, propName, value) => {
|
|
98
|
-
const propsByInstanceId = propsByInstanceIdStore.get();
|
|
99
|
-
const props = propsByInstanceId.get(instanceId);
|
|
100
|
-
const prop = props?.find((prop) => prop.name === propName);
|
|
101
|
-
if (prop?.type !== "dataSource") {
|
|
102
|
-
throw Error(`${propName} is not data source`);
|
|
103
|
-
}
|
|
104
|
-
const dataSourceId = prop.value;
|
|
105
|
-
const newValues = new Map();
|
|
106
|
-
newValues.set(dataSourceId, value);
|
|
107
|
-
onDataSourceUpdate(newValues);
|
|
108
|
-
},
|
|
109
|
-
}}
|
|
110
|
-
>
|
|
111
|
-
{root}
|
|
112
|
-
</ReactSdkContext.Provider>
|
|
113
|
-
);
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const createInstanceChildrenElements = ({
|
|
117
|
-
instances,
|
|
118
|
-
instanceSelector,
|
|
119
|
-
children,
|
|
120
|
-
Component,
|
|
121
|
-
components,
|
|
122
|
-
}: {
|
|
123
|
-
instances: Instances;
|
|
124
|
-
instanceSelector: InstanceSelector;
|
|
125
|
-
children: Instance["children"];
|
|
126
|
-
Component: ForwardRefExoticComponent<
|
|
127
|
-
WebstudioComponentProps & RefAttributes<HTMLElement>
|
|
128
|
-
>;
|
|
129
|
-
components: Components;
|
|
130
|
-
}) => {
|
|
131
|
-
const elements = [];
|
|
132
|
-
for (const child of children) {
|
|
133
|
-
if (child.type === "text") {
|
|
134
|
-
elements.push(child.value);
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
const childInstance = instances.get(child.value);
|
|
138
|
-
if (childInstance === undefined) {
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
141
|
-
const childInstanceSelector = [child.value, ...instanceSelector];
|
|
142
|
-
const children = createInstanceChildrenElements({
|
|
143
|
-
instances,
|
|
144
|
-
instanceSelector: childInstanceSelector,
|
|
145
|
-
children: childInstance.children,
|
|
146
|
-
Component,
|
|
147
|
-
components,
|
|
148
|
-
});
|
|
149
|
-
const element = createInstanceElement({
|
|
150
|
-
instance: childInstance,
|
|
151
|
-
instanceSelector: childInstanceSelector,
|
|
152
|
-
Component,
|
|
153
|
-
children,
|
|
154
|
-
components,
|
|
155
|
-
});
|
|
156
|
-
elements.push(element);
|
|
157
|
-
}
|
|
158
|
-
return elements;
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
const createInstanceElement = ({
|
|
162
|
-
Component,
|
|
163
|
-
instance,
|
|
164
|
-
instanceSelector,
|
|
165
|
-
children = [],
|
|
166
|
-
components,
|
|
167
|
-
}: {
|
|
168
|
-
instance: Instance;
|
|
169
|
-
instanceSelector: InstanceSelector;
|
|
170
|
-
Component: ForwardRefExoticComponent<
|
|
171
|
-
WebstudioComponentProps & RefAttributes<HTMLElement>
|
|
172
|
-
>;
|
|
173
|
-
children?: Array<JSX.Element | string>;
|
|
174
|
-
components: Components;
|
|
175
|
-
}) => {
|
|
176
|
-
return (
|
|
177
|
-
<Component
|
|
178
|
-
key={instance.id}
|
|
179
|
-
instance={instance}
|
|
180
|
-
instanceSelector={instanceSelector}
|
|
181
|
-
components={components}
|
|
182
|
-
>
|
|
183
|
-
{children}
|
|
184
|
-
</Component>
|
|
185
|
-
);
|
|
186
|
-
};
|
package/src/tree/index.ts
DELETED
package/src/tree/root.ts
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useRef,
|
|
3
|
-
useCallback,
|
|
4
|
-
type ForwardRefExoticComponent,
|
|
5
|
-
type RefAttributes,
|
|
6
|
-
type ReactNode,
|
|
7
|
-
} from "react";
|
|
8
|
-
import {
|
|
9
|
-
atom,
|
|
10
|
-
computed,
|
|
11
|
-
type ReadableAtom,
|
|
12
|
-
type WritableAtom,
|
|
13
|
-
} from "nanostores";
|
|
14
|
-
import { type Build, type Page } from "@webstudio-is/project-build";
|
|
15
|
-
import type { Asset } from "@webstudio-is/asset-uploader";
|
|
16
|
-
import { createElementsTree } from "./create-elements-tree";
|
|
17
|
-
import {
|
|
18
|
-
WebstudioComponent,
|
|
19
|
-
type WebstudioComponentProps,
|
|
20
|
-
} from "./webstudio-component";
|
|
21
|
-
import { getPropsByInstanceId } from "../props";
|
|
22
|
-
import type { Components } from "../components/components-utils";
|
|
23
|
-
import type { Params, DataSourceValues } from "../context";
|
|
24
|
-
import type { GeneratedUtils } from "../generator";
|
|
25
|
-
|
|
26
|
-
export type Data = {
|
|
27
|
-
page: Page;
|
|
28
|
-
pages: Array<Page>;
|
|
29
|
-
build: Build;
|
|
30
|
-
assets: Array<Asset>;
|
|
31
|
-
params?: Params;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export type RootPropsData = Omit<Data, "build"> & {
|
|
35
|
-
build: Pick<Data["build"], "instances" | "props" | "dataSources">;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
type RootProps = {
|
|
39
|
-
data: RootPropsData;
|
|
40
|
-
utils: GeneratedUtils;
|
|
41
|
-
Component?: ForwardRefExoticComponent<
|
|
42
|
-
WebstudioComponentProps & RefAttributes<HTMLElement>
|
|
43
|
-
>;
|
|
44
|
-
components: Components;
|
|
45
|
-
scripts?: ReactNode;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export const InstanceRoot = ({
|
|
49
|
-
data,
|
|
50
|
-
utils,
|
|
51
|
-
Component,
|
|
52
|
-
components,
|
|
53
|
-
scripts,
|
|
54
|
-
}: RootProps): JSX.Element | null => {
|
|
55
|
-
const {
|
|
56
|
-
indexesWithinAncestors,
|
|
57
|
-
executeComputingExpressions,
|
|
58
|
-
executeEffectfulExpression,
|
|
59
|
-
} = utils;
|
|
60
|
-
const dataSourceVariablesStoreRef = useRef<
|
|
61
|
-
undefined | WritableAtom<DataSourceValues>
|
|
62
|
-
>(undefined);
|
|
63
|
-
if (dataSourceVariablesStoreRef.current === undefined) {
|
|
64
|
-
dataSourceVariablesStoreRef.current = atom(new Map());
|
|
65
|
-
}
|
|
66
|
-
const dataSourceVariablesStore = dataSourceVariablesStoreRef.current;
|
|
67
|
-
|
|
68
|
-
const dataSourceValuesStoreRef = useRef<
|
|
69
|
-
undefined | ReadableAtom<DataSourceValues>
|
|
70
|
-
>(undefined);
|
|
71
|
-
if (dataSourceValuesStoreRef.current === undefined) {
|
|
72
|
-
dataSourceValuesStoreRef.current = computed(
|
|
73
|
-
dataSourceVariablesStore,
|
|
74
|
-
(dataSourceVariables) => {
|
|
75
|
-
// set vriables with defaults
|
|
76
|
-
const dataSourceValues: DataSourceValues = new Map();
|
|
77
|
-
for (const [dataSourceId, dataSource] of data.build.dataSources) {
|
|
78
|
-
if (dataSource.type === "variable") {
|
|
79
|
-
const value =
|
|
80
|
-
dataSourceVariables.get(dataSourceId) ?? dataSource.value.value;
|
|
81
|
-
dataSourceValues.set(dataSourceId, value);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// set expression values
|
|
86
|
-
try {
|
|
87
|
-
const result = executeComputingExpressions(dataSourceValues);
|
|
88
|
-
for (const [id, value] of result) {
|
|
89
|
-
dataSourceValues.set(id, value);
|
|
90
|
-
}
|
|
91
|
-
} catch (error) {
|
|
92
|
-
// eslint-disable-next-line no-console
|
|
93
|
-
console.error(error);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return dataSourceValues;
|
|
97
|
-
}
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
const dataSourceValuesStore = dataSourceValuesStoreRef.current;
|
|
101
|
-
|
|
102
|
-
const onDataSourceUpdate = useCallback(
|
|
103
|
-
(newValues: DataSourceValues) => {
|
|
104
|
-
const dataSourceVariables = new Map(dataSourceVariablesStore.get());
|
|
105
|
-
for (const [dataSourceId, value] of newValues) {
|
|
106
|
-
dataSourceVariables.set(dataSourceId, value);
|
|
107
|
-
}
|
|
108
|
-
dataSourceVariablesStore.set(dataSourceVariables);
|
|
109
|
-
},
|
|
110
|
-
[dataSourceVariablesStore]
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
return createElementsTree({
|
|
114
|
-
imageBaseUrl: data.params?.imageBaseUrl ?? "/",
|
|
115
|
-
assetBaseUrl: data.params?.assetBaseUrl ?? "/",
|
|
116
|
-
instances: new Map(data.build.instances),
|
|
117
|
-
rootInstanceId: data.page.rootInstanceId,
|
|
118
|
-
propsByInstanceIdStore: atom(
|
|
119
|
-
getPropsByInstanceId(new Map(data.build.props))
|
|
120
|
-
),
|
|
121
|
-
assetsStore: atom(new Map(data.assets.map((asset) => [asset.id, asset]))),
|
|
122
|
-
pagesStore: atom(new Map(data.pages.map((page) => [page.id, page]))),
|
|
123
|
-
indexesWithinAncestors,
|
|
124
|
-
executeEffectfulExpression,
|
|
125
|
-
dataSourceValuesStore,
|
|
126
|
-
onDataSourceUpdate,
|
|
127
|
-
Component: Component ?? WebstudioComponent,
|
|
128
|
-
components,
|
|
129
|
-
scripts,
|
|
130
|
-
});
|
|
131
|
-
};
|