@webstudio-is/react-sdk 0.83.0 → 0.84.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/cjs/component-renderer.js +125 -0
- package/lib/cjs/components/component-meta.js +5 -0
- package/lib/cjs/context.js +2 -1
- package/lib/cjs/css/style-rules.js +1 -1
- package/lib/cjs/embed-template.js +101 -55
- package/lib/cjs/hook.js +34 -0
- package/lib/cjs/index.js +6 -0
- package/lib/cjs/instance-utils.js +65 -0
- package/lib/cjs/props.js +12 -2
- package/lib/cjs/tree/create-elements-tree.js +5 -4
- package/lib/cjs/tree/root.js +6 -2
- package/lib/cjs/tree/webstudio-component.js +2 -0
- package/lib/component-renderer.js +111 -0
- package/lib/components/component-meta.js +5 -0
- package/lib/context.js +2 -1
- package/lib/css/style-rules.js +1 -1
- package/lib/embed-template.js +101 -55
- package/lib/hook.js +14 -0
- package/lib/index.js +8 -1
- package/lib/instance-utils.js +45 -0
- package/lib/props.js +13 -3
- package/lib/tree/create-elements-tree.js +5 -4
- package/lib/tree/root.js +6 -2
- package/lib/tree/webstudio-component.js +2 -0
- package/lib/types/component-renderer.d.ts +8 -0
- package/lib/types/components/component-meta.d.ts +9 -6
- package/lib/types/context.d.ts +2 -0
- package/lib/types/css/css.d.ts +19 -19
- package/lib/types/css/global-rules.d.ts +19 -19
- package/lib/types/css/normalize.d.ts +47 -47
- package/lib/types/embed-template.d.ts +291 -181
- package/lib/types/hook.d.ts +31 -0
- package/lib/types/index.d.ts +4 -1
- package/lib/types/instance-utils.d.ts +16 -0
- package/lib/types/instance-utils.test.d.ts +1 -0
- package/lib/types/props.d.ts +47 -46
- package/lib/types/tree/create-elements-tree.d.ts +5 -2
- package/lib/types/tree/root.d.ts +5 -2
- package/lib/types/tree/webstudio-component.d.ts +1 -0
- package/package.json +11 -11
- package/src/component-renderer.tsx +117 -0
- package/src/components/component-meta.ts +5 -0
- package/src/context.tsx +3 -0
- package/src/css/style-rules.ts +1 -1
- package/src/embed-template.test.ts +81 -70
- package/src/embed-template.ts +116 -56
- package/src/hook.ts +42 -0
- package/src/index.ts +4 -0
- package/src/instance-utils.test.ts +89 -0
- package/src/instance-utils.ts +65 -0
- package/src/props.ts +13 -1
- package/src/tree/create-elements-tree.tsx +8 -3
- package/src/tree/root.ts +8 -0
- package/src/tree/webstudio-component.tsx +1 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Instance, Prop } from "@webstudio-is/project-build";
|
|
2
|
+
/**
|
|
3
|
+
* Hooks are subscriptions to builder events
|
|
4
|
+
* with limited way to interact with it.
|
|
5
|
+
* Called independently from components.
|
|
6
|
+
*/
|
|
7
|
+
export type HookContext = {
|
|
8
|
+
setPropVariable: (instanceId: Instance["id"], propName: Prop["name"], value: unknown) => void;
|
|
9
|
+
};
|
|
10
|
+
export type InstanceSelection = Instance[];
|
|
11
|
+
type NavigatorEvent = {
|
|
12
|
+
instanceSelection: InstanceSelection;
|
|
13
|
+
};
|
|
14
|
+
export type Hook = {
|
|
15
|
+
onNavigatorSelect?: (context: HookContext, event: NavigatorEvent) => void;
|
|
16
|
+
onNavigatorUnselect?: (context: HookContext, event: NavigatorEvent) => void;
|
|
17
|
+
};
|
|
18
|
+
export declare const getClosestInstance: (instanceSelection: InstanceSelection, currentInstance: Instance, closestComponent: Instance["component"]) => {
|
|
19
|
+
type: "instance";
|
|
20
|
+
id: string;
|
|
21
|
+
component: string;
|
|
22
|
+
children: ({
|
|
23
|
+
type: "text";
|
|
24
|
+
value: string;
|
|
25
|
+
} | {
|
|
26
|
+
type: "id";
|
|
27
|
+
value: string;
|
|
28
|
+
})[];
|
|
29
|
+
label?: string | undefined;
|
|
30
|
+
} | undefined;
|
|
31
|
+
export {};
|
package/lib/types/index.d.ts
CHANGED
|
@@ -5,6 +5,9 @@ export * from "./app";
|
|
|
5
5
|
export * from "./components/components-utils";
|
|
6
6
|
export { type WsComponentPropsMeta, type WsComponentMeta, type ComponentState, type PresetStyle, componentCategories, stateCategories, defaultStates, } from "./components/component-meta";
|
|
7
7
|
export * from "./embed-template";
|
|
8
|
-
export { useInstanceProps, usePropUrl, usePropAsset, getInstanceIdFromComponentProps, } from "./props";
|
|
8
|
+
export { useInstanceProps, usePropUrl, usePropAsset, getInstanceIdFromComponentProps, getIndexWithinAncestorFromComponentProps, } from "./props";
|
|
9
9
|
export { type Params, ReactSdkContext } from "./context";
|
|
10
10
|
export { validateExpression, generateComputingExpressions, executeComputingExpressions, generateEffectfulExpression, executeEffectfulExpression, computeExpressionsDependencies, encodeDataSourceVariable, encodeVariablesMap, decodeDataSourceVariable, decodeVariablesMap, } from "./expression";
|
|
11
|
+
export { renderComponentTemplate } from "./component-renderer";
|
|
12
|
+
export { getIndexesWithinAncestors } from "./instance-utils";
|
|
13
|
+
export * from "./hook";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Instance } from "@webstudio-is/project-build";
|
|
2
|
+
import type { WsComponentMeta } from "./components/component-meta";
|
|
3
|
+
export type IndexesWithinAncestors = Map<Instance["id"], number>;
|
|
4
|
+
export declare const getIndexesWithinAncestors: (metas: Map<Instance["component"], WsComponentMeta>, instances: Map<string, {
|
|
5
|
+
type: "instance";
|
|
6
|
+
id: string;
|
|
7
|
+
component: string;
|
|
8
|
+
children: ({
|
|
9
|
+
type: "text";
|
|
10
|
+
value: string;
|
|
11
|
+
} | {
|
|
12
|
+
type: "id";
|
|
13
|
+
value: string;
|
|
14
|
+
})[];
|
|
15
|
+
label?: string | undefined;
|
|
16
|
+
}>, rootIds: Instance["id"][]) => IndexesWithinAncestors;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/lib/types/props.d.ts
CHANGED
|
@@ -3,35 +3,34 @@ import type { Asset, Assets } from "@webstudio-is/asset-uploader";
|
|
|
3
3
|
export type PropsByInstanceId = Map<Instance["id"], Prop[]>;
|
|
4
4
|
export type Pages = Map<Page["id"], Page>;
|
|
5
5
|
export declare const getPropsByInstanceId: (props: Map<string, {
|
|
6
|
-
name: string;
|
|
7
6
|
type: "number";
|
|
8
7
|
value: number;
|
|
9
8
|
id: string;
|
|
9
|
+
name: string;
|
|
10
10
|
instanceId: string;
|
|
11
11
|
required?: boolean | undefined;
|
|
12
12
|
} | {
|
|
13
|
-
name: string;
|
|
14
13
|
type: "string";
|
|
15
14
|
value: string;
|
|
16
15
|
id: string;
|
|
16
|
+
name: string;
|
|
17
17
|
instanceId: string;
|
|
18
18
|
required?: boolean | undefined;
|
|
19
19
|
} | {
|
|
20
|
-
name: string;
|
|
21
20
|
type: "boolean";
|
|
22
21
|
value: boolean;
|
|
23
22
|
id: string;
|
|
23
|
+
name: string;
|
|
24
24
|
instanceId: string;
|
|
25
25
|
required?: boolean | undefined;
|
|
26
26
|
} | {
|
|
27
|
-
name: string;
|
|
28
27
|
type: "asset";
|
|
29
28
|
value: string;
|
|
30
29
|
id: string;
|
|
30
|
+
name: string;
|
|
31
31
|
instanceId: string;
|
|
32
32
|
required?: boolean | undefined;
|
|
33
33
|
} | {
|
|
34
|
-
name: string;
|
|
35
34
|
type: "page";
|
|
36
35
|
value: (string | {
|
|
37
36
|
instanceId: string;
|
|
@@ -41,24 +40,24 @@ export declare const getPropsByInstanceId: (props: Map<string, {
|
|
|
41
40
|
pageId: string;
|
|
42
41
|
} | undefined);
|
|
43
42
|
id: string;
|
|
43
|
+
name: string;
|
|
44
44
|
instanceId: string;
|
|
45
45
|
required?: boolean | undefined;
|
|
46
46
|
} | {
|
|
47
|
-
name: string;
|
|
48
47
|
type: "string[]";
|
|
49
48
|
value: string[];
|
|
50
49
|
id: string;
|
|
50
|
+
name: string;
|
|
51
51
|
instanceId: string;
|
|
52
52
|
required?: boolean | undefined;
|
|
53
53
|
} | {
|
|
54
|
-
name: string;
|
|
55
54
|
type: "dataSource";
|
|
56
55
|
value: string;
|
|
57
56
|
id: string;
|
|
57
|
+
name: string;
|
|
58
58
|
instanceId: string;
|
|
59
59
|
required?: boolean | undefined;
|
|
60
60
|
} | {
|
|
61
|
-
name: string;
|
|
62
61
|
type: "action";
|
|
63
62
|
value: {
|
|
64
63
|
code: string;
|
|
@@ -66,108 +65,109 @@ export declare const getPropsByInstanceId: (props: Map<string, {
|
|
|
66
65
|
args: string[];
|
|
67
66
|
}[];
|
|
68
67
|
id: string;
|
|
68
|
+
name: string;
|
|
69
69
|
instanceId: string;
|
|
70
70
|
required?: boolean | undefined;
|
|
71
71
|
}>) => PropsByInstanceId;
|
|
72
72
|
export declare const useInstanceProps: (instanceId: Instance["id"]) => Record<string, unknown>;
|
|
73
73
|
export declare const usePropAsset: (instanceId: Instance["id"], name: string) => {
|
|
74
|
-
name: string;
|
|
75
74
|
type: "font";
|
|
76
|
-
format: "ttf" | "woff" | "woff2" | "otf";
|
|
77
75
|
id: string;
|
|
78
|
-
|
|
79
|
-
size: number;
|
|
80
|
-
description: string | null;
|
|
81
|
-
createdAt: string;
|
|
76
|
+
name: string;
|
|
82
77
|
meta: ({
|
|
83
|
-
style: "normal" | "italic" | "oblique";
|
|
84
78
|
weight: number;
|
|
79
|
+
style: "normal" | "italic" | "oblique";
|
|
85
80
|
family: string;
|
|
86
81
|
} | {
|
|
87
82
|
variationAxes: Partial<Record<"wght" | "wdth" | "slnt" | "opsz" | "ital" | "GRAD" | "XTRA" | "XOPQ" | "YOPQ" | "YTLC" | "YTUC" | "YTAS" | "YTDE" | "YTFI", {
|
|
88
|
-
name: string;
|
|
89
83
|
min: number;
|
|
90
|
-
default: number;
|
|
91
84
|
max: number;
|
|
85
|
+
name: string;
|
|
86
|
+
default: number;
|
|
92
87
|
}>>;
|
|
93
88
|
family: string;
|
|
94
89
|
}) & ({
|
|
95
|
-
style: "normal" | "italic" | "oblique";
|
|
96
90
|
weight: number;
|
|
91
|
+
style: "normal" | "italic" | "oblique";
|
|
97
92
|
family: string;
|
|
98
93
|
} | {
|
|
99
94
|
variationAxes: Partial<Record<"wght" | "wdth" | "slnt" | "opsz" | "ital" | "GRAD" | "XTRA" | "XOPQ" | "YOPQ" | "YTLC" | "YTUC" | "YTAS" | "YTDE" | "YTFI", {
|
|
100
|
-
name: string;
|
|
101
95
|
min: number;
|
|
102
|
-
default: number;
|
|
103
96
|
max: number;
|
|
97
|
+
name: string;
|
|
98
|
+
default: number;
|
|
104
99
|
}>>;
|
|
105
100
|
family: string;
|
|
106
101
|
} | undefined);
|
|
107
|
-
} | {
|
|
108
|
-
name: string;
|
|
109
|
-
type: "image";
|
|
110
|
-
format: string;
|
|
111
|
-
id: string;
|
|
112
|
-
projectId: string;
|
|
113
102
|
size: number;
|
|
114
103
|
description: string | null;
|
|
104
|
+
format: "ttf" | "woff" | "woff2" | "otf";
|
|
105
|
+
projectId: string;
|
|
115
106
|
createdAt: string;
|
|
107
|
+
} | {
|
|
108
|
+
type: "image";
|
|
109
|
+
id: string;
|
|
110
|
+
name: string;
|
|
116
111
|
meta: {
|
|
117
|
-
width: number;
|
|
118
112
|
height: number;
|
|
113
|
+
width: number;
|
|
119
114
|
};
|
|
115
|
+
size: number;
|
|
116
|
+
description: string | null;
|
|
117
|
+
format: string;
|
|
118
|
+
projectId: string;
|
|
119
|
+
createdAt: string;
|
|
120
120
|
} | undefined;
|
|
121
121
|
export declare const resolveUrlProp: (instanceId: Instance["id"], name: string, { props, pages, assets, }: {
|
|
122
122
|
props: PropsByInstanceId;
|
|
123
123
|
pages: Pages;
|
|
124
124
|
assets: Map<string, {
|
|
125
|
-
name: string;
|
|
126
125
|
type: "font";
|
|
127
|
-
format: "ttf" | "woff" | "woff2" | "otf";
|
|
128
126
|
id: string;
|
|
129
|
-
|
|
130
|
-
size: number;
|
|
131
|
-
description: string | null;
|
|
132
|
-
createdAt: string;
|
|
127
|
+
name: string;
|
|
133
128
|
meta: ({
|
|
134
|
-
style: "normal" | "italic" | "oblique";
|
|
135
129
|
weight: number;
|
|
130
|
+
style: "normal" | "italic" | "oblique";
|
|
136
131
|
family: string;
|
|
137
132
|
} | {
|
|
138
133
|
variationAxes: Partial<Record<"wght" | "wdth" | "slnt" | "opsz" | "ital" | "GRAD" | "XTRA" | "XOPQ" | "YOPQ" | "YTLC" | "YTUC" | "YTAS" | "YTDE" | "YTFI", {
|
|
139
|
-
name: string;
|
|
140
134
|
min: number;
|
|
141
|
-
default: number;
|
|
142
135
|
max: number;
|
|
136
|
+
name: string;
|
|
137
|
+
default: number;
|
|
143
138
|
}>>;
|
|
144
139
|
family: string;
|
|
145
140
|
}) & ({
|
|
146
|
-
style: "normal" | "italic" | "oblique";
|
|
147
141
|
weight: number;
|
|
142
|
+
style: "normal" | "italic" | "oblique";
|
|
148
143
|
family: string;
|
|
149
144
|
} | {
|
|
150
145
|
variationAxes: Partial<Record<"wght" | "wdth" | "slnt" | "opsz" | "ital" | "GRAD" | "XTRA" | "XOPQ" | "YOPQ" | "YTLC" | "YTUC" | "YTAS" | "YTDE" | "YTFI", {
|
|
151
|
-
name: string;
|
|
152
146
|
min: number;
|
|
153
|
-
default: number;
|
|
154
147
|
max: number;
|
|
148
|
+
name: string;
|
|
149
|
+
default: number;
|
|
155
150
|
}>>;
|
|
156
151
|
family: string;
|
|
157
152
|
} | undefined);
|
|
158
|
-
} | {
|
|
159
|
-
name: string;
|
|
160
|
-
type: "image";
|
|
161
|
-
format: string;
|
|
162
|
-
id: string;
|
|
163
|
-
projectId: string;
|
|
164
153
|
size: number;
|
|
165
154
|
description: string | null;
|
|
155
|
+
format: "ttf" | "woff" | "woff2" | "otf";
|
|
156
|
+
projectId: string;
|
|
166
157
|
createdAt: string;
|
|
158
|
+
} | {
|
|
159
|
+
type: "image";
|
|
160
|
+
id: string;
|
|
161
|
+
name: string;
|
|
167
162
|
meta: {
|
|
168
|
-
width: number;
|
|
169
163
|
height: number;
|
|
164
|
+
width: number;
|
|
170
165
|
};
|
|
166
|
+
size: number;
|
|
167
|
+
description: string | null;
|
|
168
|
+
format: string;
|
|
169
|
+
projectId: string;
|
|
170
|
+
createdAt: string;
|
|
171
171
|
} | undefined>;
|
|
172
172
|
}) => {
|
|
173
173
|
type: "page";
|
|
@@ -194,3 +194,4 @@ export declare const usePropUrl: (instanceId: Instance["id"], name: string) => {
|
|
|
194
194
|
url: string;
|
|
195
195
|
} | undefined;
|
|
196
196
|
export declare const getInstanceIdFromComponentProps: (props: Record<string, unknown>) => string;
|
|
197
|
+
export declare const getIndexWithinAncestorFromComponentProps: (props: Record<string, unknown>) => string | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ForwardRefExoticComponent, type RefAttributes } from "react";
|
|
1
|
+
import { type ForwardRefExoticComponent, type RefAttributes, type ReactNode } from "react";
|
|
2
2
|
import type { ReadableAtom } from "nanostores";
|
|
3
3
|
import type { Assets } from "@webstudio-is/asset-uploader";
|
|
4
4
|
import type { Instance, Instances } from "@webstudio-is/project-build";
|
|
@@ -6,7 +6,8 @@ import type { Components } from "../components/components-utils";
|
|
|
6
6
|
import { type Params, type DataSourceValues } from "../context";
|
|
7
7
|
import type { Pages, PropsByInstanceId } from "../props";
|
|
8
8
|
import type { WebstudioComponentProps } from "./webstudio-component";
|
|
9
|
-
|
|
9
|
+
import type { IndexesWithinAncestors } from "../instance-utils";
|
|
10
|
+
export declare const createElementsTree: ({ renderer, imageBaseUrl, assetBaseUrl, instances, rootInstanceId, propsByInstanceIdStore, assetsStore, pagesStore, dataSourceValuesStore, executeEffectfulExpression, onDataSourceUpdate, indexesWithinAncestors, Component, components, scripts, }: Params & {
|
|
10
11
|
instances: Map<string, {
|
|
11
12
|
type: "instance";
|
|
12
13
|
id: string;
|
|
@@ -27,6 +28,8 @@ export declare const createElementsTree: ({ renderer, imageBaseUrl, assetBaseUrl
|
|
|
27
28
|
executeEffectfulExpression: (expression: string, args: DataSourceValues, values: DataSourceValues) => DataSourceValues;
|
|
28
29
|
dataSourceValuesStore: ReadableAtom<DataSourceValues>;
|
|
29
30
|
onDataSourceUpdate: (newValues: DataSourceValues) => void;
|
|
31
|
+
indexesWithinAncestors: IndexesWithinAncestors;
|
|
30
32
|
Component: ForwardRefExoticComponent<WebstudioComponentProps & RefAttributes<HTMLElement>>;
|
|
31
33
|
components: Components;
|
|
34
|
+
scripts?: ReactNode;
|
|
32
35
|
}) => import("react/jsx-runtime").JSX.Element | null;
|
package/lib/types/tree/root.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { type ForwardRefExoticComponent, type RefAttributes } from "react";
|
|
1
|
+
import { type ForwardRefExoticComponent, type RefAttributes, type ReactNode } from "react";
|
|
2
2
|
import { type Build, type Page } from "@webstudio-is/project-build";
|
|
3
3
|
import type { Asset } from "@webstudio-is/asset-uploader";
|
|
4
4
|
import { type WebstudioComponentProps } from "./webstudio-component";
|
|
5
5
|
import type { Components } from "../components/components-utils";
|
|
6
6
|
import type { Params, DataSourceValues } from "../context";
|
|
7
|
+
import type { IndexesWithinAncestors } from "../instance-utils";
|
|
7
8
|
export type Data = {
|
|
8
9
|
page: Page;
|
|
9
10
|
pages: Array<Page>;
|
|
@@ -16,10 +17,12 @@ export type RootPropsData = Omit<Data, "build"> & {
|
|
|
16
17
|
};
|
|
17
18
|
type RootProps = {
|
|
18
19
|
data: RootPropsData;
|
|
20
|
+
indexesWithinAncestors: IndexesWithinAncestors;
|
|
19
21
|
executeComputingExpressions: (values: DataSourceValues) => DataSourceValues;
|
|
20
22
|
executeEffectfulExpression: (expression: string, args: DataSourceValues, values: DataSourceValues) => DataSourceValues;
|
|
21
23
|
Component?: ForwardRefExoticComponent<WebstudioComponentProps & RefAttributes<HTMLElement>>;
|
|
22
24
|
components: Components;
|
|
25
|
+
scripts?: ReactNode;
|
|
23
26
|
};
|
|
24
|
-
export declare const InstanceRoot: ({ data, executeComputingExpressions, executeEffectfulExpression, Component, components, }: RootProps) => JSX.Element | null;
|
|
27
|
+
export declare const InstanceRoot: ({ data, indexesWithinAncestors, executeComputingExpressions, executeEffectfulExpression, Component, components, scripts, }: RootProps) => JSX.Element | null;
|
|
25
28
|
export {};
|
|
@@ -13,6 +13,7 @@ export declare const idAttribute: "data-ws-id";
|
|
|
13
13
|
export declare const selectorIdAttribute: "data-ws-selector";
|
|
14
14
|
export declare const componentAttribute: "data-ws-component";
|
|
15
15
|
export declare const showAttribute: "data-ws-show";
|
|
16
|
+
export declare const indexAttribute: "data-ws-index";
|
|
16
17
|
export declare const collapsedAttribute: "data-ws-collapsed";
|
|
17
18
|
export type WebstudioAttributes = {
|
|
18
19
|
[idAttribute]?: string | undefined;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webstudio-is/react-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.84.0",
|
|
4
4
|
"description": "Webstudio JavaScript / TypeScript API",
|
|
5
5
|
"author": "Webstudio <github@webstudio.is>",
|
|
6
6
|
"homepage": "https://webstudio.is",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"devDependencies": {
|
|
9
9
|
"@jest/globals": "^29.6.2",
|
|
10
|
-
"@remix-run/react": "^1.
|
|
10
|
+
"@remix-run/react": "^1.19.2",
|
|
11
11
|
"@types/react": "^18.2.16",
|
|
12
12
|
"@types/react-dom": "^18.2.7",
|
|
13
13
|
"jest": "^29.6.2",
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
"type-fest": "^3.7.1",
|
|
17
17
|
"typescript": "5.1.6",
|
|
18
18
|
"zod": "^3.21.4",
|
|
19
|
-
"@webstudio-is/jest-config": "^1.0.
|
|
19
|
+
"@webstudio-is/jest-config": "^1.0.7",
|
|
20
20
|
"@webstudio-is/scripts": "^0.0.0",
|
|
21
|
-
"@webstudio-is/tsconfig": "^1.0.
|
|
21
|
+
"@webstudio-is/tsconfig": "^1.0.7"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"@remix-run/react": "^1.
|
|
24
|
+
"@remix-run/react": "^1.19.1",
|
|
25
25
|
"react": "^18.2.0",
|
|
26
26
|
"react-dom": "^18.2.0",
|
|
27
27
|
"zod": "^3.19.1"
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"nanoevents": "^8.0.0",
|
|
35
35
|
"nanoid": "^4.0.2",
|
|
36
36
|
"nanostores": "^0.9.3",
|
|
37
|
-
"@webstudio-is/
|
|
38
|
-
"@webstudio-is/css-
|
|
39
|
-
"@webstudio-is/
|
|
40
|
-
"@webstudio-is/
|
|
41
|
-
"@webstudio-is/
|
|
42
|
-
"@webstudio-is/
|
|
37
|
+
"@webstudio-is/css-data": "^0.84.0",
|
|
38
|
+
"@webstudio-is/css-engine": "^0.84.0",
|
|
39
|
+
"@webstudio-is/fonts": "^0.84.0",
|
|
40
|
+
"@webstudio-is/generate-arg-types": "^0.84.0",
|
|
41
|
+
"@webstudio-is/project-build": "^0.84.0",
|
|
42
|
+
"@webstudio-is/asset-uploader": "^0.84.0"
|
|
43
43
|
},
|
|
44
44
|
"exports": {
|
|
45
45
|
".": {
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { ExoticComponent } from "react";
|
|
2
|
+
import type { Instance } from "@webstudio-is/project-build";
|
|
3
|
+
import { getStyleDeclKey } from "@webstudio-is/project-build";
|
|
4
|
+
import type { WsComponentMeta } from "./components/component-meta";
|
|
5
|
+
import { generateDataFromEmbedTemplate } from "./embed-template";
|
|
6
|
+
import { generateCssText } from "./css";
|
|
7
|
+
import { InstanceRoot, WebstudioComponent } from "./tree";
|
|
8
|
+
import {
|
|
9
|
+
decodeVariablesMap,
|
|
10
|
+
encodeDataSourceVariable,
|
|
11
|
+
encodeVariablesMap,
|
|
12
|
+
executeComputingExpressions,
|
|
13
|
+
executeEffectfulExpression,
|
|
14
|
+
} from "./expression";
|
|
15
|
+
import { getIndexesWithinAncestors } from "./instance-utils";
|
|
16
|
+
|
|
17
|
+
export const renderComponentTemplate = ({
|
|
18
|
+
name,
|
|
19
|
+
metas: metasRecord,
|
|
20
|
+
components,
|
|
21
|
+
}: {
|
|
22
|
+
name: Instance["component"];
|
|
23
|
+
metas: Record<string, WsComponentMeta>;
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
|
+
components: Record<string, ExoticComponent<any>>;
|
|
26
|
+
}) => {
|
|
27
|
+
const metas = new Map(Object.entries(metasRecord));
|
|
28
|
+
const data = generateDataFromEmbedTemplate(
|
|
29
|
+
metas.get(name)?.template ?? [
|
|
30
|
+
{
|
|
31
|
+
type: "instance",
|
|
32
|
+
component: name,
|
|
33
|
+
children: [],
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
"base"
|
|
37
|
+
);
|
|
38
|
+
const instances: [Instance["id"], Instance][] = [
|
|
39
|
+
[
|
|
40
|
+
"root",
|
|
41
|
+
{
|
|
42
|
+
type: "instance",
|
|
43
|
+
id: "root",
|
|
44
|
+
component: "Box",
|
|
45
|
+
children: data.children,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
...data.instances.map(
|
|
49
|
+
(instance) => [instance.id, instance] satisfies [Instance["id"], Instance]
|
|
50
|
+
),
|
|
51
|
+
];
|
|
52
|
+
return (
|
|
53
|
+
<>
|
|
54
|
+
<style>
|
|
55
|
+
{generateCssText(
|
|
56
|
+
{
|
|
57
|
+
assets: [],
|
|
58
|
+
breakpoints: [["base", { id: "base", label: "base" }]],
|
|
59
|
+
styles: data.styles.map((item) => [getStyleDeclKey(item), item]),
|
|
60
|
+
styleSourceSelections: data.styleSourceSelections.map((item) => [
|
|
61
|
+
item.instanceId,
|
|
62
|
+
item,
|
|
63
|
+
]),
|
|
64
|
+
componentMetas: metas,
|
|
65
|
+
},
|
|
66
|
+
{ assetBaseUrl: "/" }
|
|
67
|
+
)}
|
|
68
|
+
</style>
|
|
69
|
+
<InstanceRoot
|
|
70
|
+
data={{
|
|
71
|
+
page: {
|
|
72
|
+
path: "",
|
|
73
|
+
id: "",
|
|
74
|
+
name: "",
|
|
75
|
+
title: "",
|
|
76
|
+
meta: {},
|
|
77
|
+
rootInstanceId: "root",
|
|
78
|
+
},
|
|
79
|
+
pages: [],
|
|
80
|
+
assets: [],
|
|
81
|
+
build: {
|
|
82
|
+
instances,
|
|
83
|
+
props: data.props.map((prop) => [prop.id, prop]),
|
|
84
|
+
dataSources: data.dataSources.map((dataSource) => [
|
|
85
|
+
dataSource.id,
|
|
86
|
+
dataSource,
|
|
87
|
+
]),
|
|
88
|
+
},
|
|
89
|
+
}}
|
|
90
|
+
executeComputingExpressions={(values) => {
|
|
91
|
+
const expressions = new Map<string, string>();
|
|
92
|
+
for (const dataSource of data.dataSources) {
|
|
93
|
+
const name = encodeDataSourceVariable(dataSource.id);
|
|
94
|
+
if (dataSource.type === "expression") {
|
|
95
|
+
expressions.set(name, dataSource.code);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return decodeVariablesMap(
|
|
99
|
+
executeComputingExpressions(expressions, encodeVariablesMap(values))
|
|
100
|
+
);
|
|
101
|
+
}}
|
|
102
|
+
executeEffectfulExpression={(code, args, values) => {
|
|
103
|
+
return decodeVariablesMap(
|
|
104
|
+
executeEffectfulExpression(code, args, encodeVariablesMap(values))
|
|
105
|
+
);
|
|
106
|
+
}}
|
|
107
|
+
Component={WebstudioComponent}
|
|
108
|
+
components={new Map(Object.entries(components))}
|
|
109
|
+
indexesWithinAncestors={getIndexesWithinAncestors(
|
|
110
|
+
metas,
|
|
111
|
+
new Map(instances),
|
|
112
|
+
["root"]
|
|
113
|
+
)}
|
|
114
|
+
/>
|
|
115
|
+
</>
|
|
116
|
+
);
|
|
117
|
+
};
|
|
@@ -53,6 +53,11 @@ const WsComponentMeta = z.object({
|
|
|
53
53
|
type: z.enum(["container", "control", "embed", "rich-text-child"]),
|
|
54
54
|
requiredAncestors: z.optional(z.array(z.string())),
|
|
55
55
|
invalidAncestors: z.optional(z.array(z.string())),
|
|
56
|
+
// when this field is specified component receives
|
|
57
|
+
// prop with index of same components withiin specified ancestor
|
|
58
|
+
// important to automatically enumerate collections without
|
|
59
|
+
// naming every item manually
|
|
60
|
+
indexWithinAncestor: z.optional(z.string()),
|
|
56
61
|
stylable: z.optional(z.boolean()),
|
|
57
62
|
// specifies whether the instance can be deleted,
|
|
58
63
|
// copied or dragged out of its parent instance
|
package/src/context.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import { createContext } from "react";
|
|
|
3
3
|
import type { Assets } from "@webstudio-is/asset-uploader";
|
|
4
4
|
import type { DataSource, Instance, Prop } from "@webstudio-is/project-build";
|
|
5
5
|
import type { Pages, PropsByInstanceId } from "./props";
|
|
6
|
+
import type { IndexesWithinAncestors } from "./instance-utils";
|
|
6
7
|
|
|
7
8
|
export type Params = {
|
|
8
9
|
renderer?: "canvas" | "preview";
|
|
@@ -50,6 +51,7 @@ export const ReactSdkContext = createContext<
|
|
|
50
51
|
prop: Prop["name"],
|
|
51
52
|
value: unknown
|
|
52
53
|
) => void;
|
|
54
|
+
indexesWithinAncestors: IndexesWithinAncestors;
|
|
53
55
|
}
|
|
54
56
|
>({
|
|
55
57
|
imageBaseUrl: "/",
|
|
@@ -67,4 +69,5 @@ export const ReactSdkContext = createContext<
|
|
|
67
69
|
setBoundDataSourceValue: () => {
|
|
68
70
|
throw Error("React SDK setBoundDataSourceValue is not implemented");
|
|
69
71
|
},
|
|
72
|
+
indexesWithinAncestors: new Map(),
|
|
70
73
|
});
|
package/src/css/style-rules.ts
CHANGED
|
@@ -86,7 +86,7 @@ export const getPresetStyleRules = (
|
|
|
86
86
|
const presetStyleRules = new Map<string, Style>();
|
|
87
87
|
for (const [tag, styles] of Object.entries(presetStyle)) {
|
|
88
88
|
for (const styleDecl of styles) {
|
|
89
|
-
const selector = `${tag}:where([${componentAttribute}
|
|
89
|
+
const selector = `${tag}:where([${componentAttribute}="${component}"])${
|
|
90
90
|
styleDecl.state ?? ""
|
|
91
91
|
}`;
|
|
92
92
|
let rule = presetStyleRules.get(selector);
|