@webstudio-is/react-sdk 0.82.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/LICENSE +661 -21
- package/lib/cjs/component-renderer.js +125 -0
- package/lib/cjs/components/component-meta.js +10 -0
- package/lib/cjs/components/components-utils.js +1 -0
- package/lib/cjs/context.js +2 -1
- package/lib/cjs/css/index.js +0 -1
- package/lib/cjs/css/style-rules.js +1 -1
- package/lib/cjs/embed-template.js +130 -55
- package/lib/cjs/expression.js +47 -4
- package/lib/cjs/hook.js +34 -0
- package/lib/cjs/index.js +7 -0
- package/lib/cjs/instance-utils.js +65 -0
- package/lib/cjs/props.js +18 -3
- package/lib/cjs/tree/create-elements-tree.js +5 -4
- package/lib/cjs/tree/root.js +7 -2
- package/lib/cjs/tree/webstudio-component.js +26 -10
- package/lib/component-renderer.js +111 -0
- package/lib/components/component-meta.js +10 -0
- package/lib/components/components-utils.js +1 -0
- package/lib/context.js +2 -1
- package/lib/css/index.js +0 -1
- package/lib/css/style-rules.js +1 -1
- package/lib/embed-template.js +138 -55
- package/lib/expression.js +47 -4
- package/lib/hook.js +14 -0
- package/lib/index.js +10 -1
- package/lib/instance-utils.js +45 -0
- package/lib/props.js +19 -4
- package/lib/tree/create-elements-tree.js +8 -5
- package/lib/tree/root.js +14 -4
- package/lib/tree/webstudio-component.js +27 -11
- package/lib/types/app/root.d.ts +1 -2
- package/lib/types/component-renderer.d.ts +8 -0
- package/lib/types/components/component-meta.d.ts +14 -8
- package/lib/types/context.d.ts +3 -1
- package/lib/types/css/css.d.ts +19 -19
- package/lib/types/css/global-rules.d.ts +19 -19
- package/lib/types/css/index.d.ts +0 -1
- package/lib/types/css/normalize.d.ts +47 -47
- package/lib/types/embed-template.d.ts +297 -174
- package/lib/types/expression.d.ts +3 -2
- package/lib/types/hook.d.ts +31 -0
- package/lib/types/index.d.ts +5 -2
- 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 +48 -46
- package/lib/types/tree/create-elements-tree.d.ts +9 -6
- package/lib/types/tree/root.d.ts +8 -5
- package/lib/types/tree/webstudio-component.d.ts +16 -7
- package/package.json +18 -19
- package/src/component-renderer.tsx +117 -0
- package/src/components/component-meta.ts +10 -0
- package/src/context.tsx +4 -0
- package/src/css/index.ts +0 -1
- package/src/css/style-rules.ts +1 -1
- package/src/embed-template.test.ts +113 -26
- package/src/embed-template.ts +149 -56
- package/src/expression.test.ts +74 -6
- package/src/expression.ts +55 -2
- package/src/hook.ts +42 -0
- package/src/index.ts +5 -0
- package/src/instance-utils.test.ts +89 -0
- package/src/instance-utils.ts +65 -0
- package/src/props.ts +19 -2
- package/src/tree/create-elements-tree.tsx +25 -8
- package/src/tree/root.ts +22 -3
- package/src/tree/webstudio-component.tsx +42 -14
- package/lib/cjs/css/get-browser-style.js +0 -83
- package/lib/css/get-browser-style.js +0 -65
- package/lib/types/css/get-browser-style.d.ts +0 -2
- package/src/css/get-browser-style.ts +0 -81
|
@@ -9,8 +9,9 @@ export declare const validateExpression: (code: string, options?: {
|
|
|
9
9
|
*/
|
|
10
10
|
export declare const generateComputingExpressions: (expressions: Map<string, string>, allowedVariables: Set<string>) => string;
|
|
11
11
|
export declare const executeComputingExpressions: (expressions: Map<string, string>, variables: Map<string, unknown>) => Map<string, unknown>;
|
|
12
|
-
export declare const generateEffectfulExpression: (code: string, allowedVariables: Set<string>) => string;
|
|
13
|
-
export declare const executeEffectfulExpression: (code: string, variables: Map<string, unknown>) => Map<string, unknown>;
|
|
12
|
+
export declare const generateEffectfulExpression: (code: string, args: Set<string>, allowedVariables: Set<string>) => string;
|
|
13
|
+
export declare const executeEffectfulExpression: (code: string, args: Map<string, unknown>, variables: Map<string, unknown>) => Map<string, unknown>;
|
|
14
|
+
export declare const computeExpressionsDependencies: (expressions: Map<string, string>) => Map<string, Set<string>>;
|
|
14
15
|
type Values = Map<string, unknown>;
|
|
15
16
|
export declare const encodeDataSourceVariable: (id: string) => string;
|
|
16
17
|
export declare const encodeVariablesMap: (values: Values) => Values;
|
|
@@ -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
|
-
export { validateExpression, generateComputingExpressions, executeComputingExpressions, generateEffectfulExpression, executeEffectfulExpression, encodeDataSourceVariable, encodeVariablesMap, decodeDataSourceVariable, decodeVariablesMap, } from "./expression";
|
|
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,132 +40,134 @@ 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;
|
|
65
64
|
type: "execute";
|
|
65
|
+
args: string[];
|
|
66
66
|
}[];
|
|
67
67
|
id: string;
|
|
68
|
+
name: string;
|
|
68
69
|
instanceId: string;
|
|
69
70
|
required?: boolean | undefined;
|
|
70
71
|
}>) => PropsByInstanceId;
|
|
71
72
|
export declare const useInstanceProps: (instanceId: Instance["id"]) => Record<string, unknown>;
|
|
72
73
|
export declare const usePropAsset: (instanceId: Instance["id"], name: string) => {
|
|
73
|
-
name: string;
|
|
74
74
|
type: "font";
|
|
75
|
-
format: "ttf" | "woff" | "woff2" | "otf";
|
|
76
75
|
id: string;
|
|
77
|
-
|
|
78
|
-
size: number;
|
|
79
|
-
description: string | null;
|
|
80
|
-
createdAt: string;
|
|
76
|
+
name: string;
|
|
81
77
|
meta: ({
|
|
82
|
-
style: "normal" | "italic" | "oblique";
|
|
83
78
|
weight: number;
|
|
79
|
+
style: "normal" | "italic" | "oblique";
|
|
84
80
|
family: string;
|
|
85
81
|
} | {
|
|
86
82
|
variationAxes: Partial<Record<"wght" | "wdth" | "slnt" | "opsz" | "ital" | "GRAD" | "XTRA" | "XOPQ" | "YOPQ" | "YTLC" | "YTUC" | "YTAS" | "YTDE" | "YTFI", {
|
|
87
|
-
name: string;
|
|
88
83
|
min: number;
|
|
89
|
-
default: number;
|
|
90
84
|
max: number;
|
|
85
|
+
name: string;
|
|
86
|
+
default: number;
|
|
91
87
|
}>>;
|
|
92
88
|
family: string;
|
|
93
89
|
}) & ({
|
|
94
|
-
style: "normal" | "italic" | "oblique";
|
|
95
90
|
weight: number;
|
|
91
|
+
style: "normal" | "italic" | "oblique";
|
|
96
92
|
family: string;
|
|
97
93
|
} | {
|
|
98
94
|
variationAxes: Partial<Record<"wght" | "wdth" | "slnt" | "opsz" | "ital" | "GRAD" | "XTRA" | "XOPQ" | "YOPQ" | "YTLC" | "YTUC" | "YTAS" | "YTDE" | "YTFI", {
|
|
99
|
-
name: string;
|
|
100
95
|
min: number;
|
|
101
|
-
default: number;
|
|
102
96
|
max: number;
|
|
97
|
+
name: string;
|
|
98
|
+
default: number;
|
|
103
99
|
}>>;
|
|
104
100
|
family: string;
|
|
105
101
|
} | undefined);
|
|
106
|
-
} | {
|
|
107
|
-
name: string;
|
|
108
|
-
type: "image";
|
|
109
|
-
format: string;
|
|
110
|
-
id: string;
|
|
111
|
-
projectId: string;
|
|
112
102
|
size: number;
|
|
113
103
|
description: string | null;
|
|
104
|
+
format: "ttf" | "woff" | "woff2" | "otf";
|
|
105
|
+
projectId: string;
|
|
114
106
|
createdAt: string;
|
|
107
|
+
} | {
|
|
108
|
+
type: "image";
|
|
109
|
+
id: string;
|
|
110
|
+
name: string;
|
|
115
111
|
meta: {
|
|
116
|
-
width: number;
|
|
117
112
|
height: number;
|
|
113
|
+
width: number;
|
|
118
114
|
};
|
|
115
|
+
size: number;
|
|
116
|
+
description: string | null;
|
|
117
|
+
format: string;
|
|
118
|
+
projectId: string;
|
|
119
|
+
createdAt: string;
|
|
119
120
|
} | undefined;
|
|
120
121
|
export declare const resolveUrlProp: (instanceId: Instance["id"], name: string, { props, pages, assets, }: {
|
|
121
122
|
props: PropsByInstanceId;
|
|
122
123
|
pages: Pages;
|
|
123
124
|
assets: Map<string, {
|
|
124
|
-
name: string;
|
|
125
125
|
type: "font";
|
|
126
|
-
format: "ttf" | "woff" | "woff2" | "otf";
|
|
127
126
|
id: string;
|
|
128
|
-
|
|
129
|
-
size: number;
|
|
130
|
-
description: string | null;
|
|
131
|
-
createdAt: string;
|
|
127
|
+
name: string;
|
|
132
128
|
meta: ({
|
|
133
|
-
style: "normal" | "italic" | "oblique";
|
|
134
129
|
weight: number;
|
|
130
|
+
style: "normal" | "italic" | "oblique";
|
|
135
131
|
family: string;
|
|
136
132
|
} | {
|
|
137
133
|
variationAxes: Partial<Record<"wght" | "wdth" | "slnt" | "opsz" | "ital" | "GRAD" | "XTRA" | "XOPQ" | "YOPQ" | "YTLC" | "YTUC" | "YTAS" | "YTDE" | "YTFI", {
|
|
138
|
-
name: string;
|
|
139
134
|
min: number;
|
|
140
|
-
default: number;
|
|
141
135
|
max: number;
|
|
136
|
+
name: string;
|
|
137
|
+
default: number;
|
|
142
138
|
}>>;
|
|
143
139
|
family: string;
|
|
144
140
|
}) & ({
|
|
145
|
-
style: "normal" | "italic" | "oblique";
|
|
146
141
|
weight: number;
|
|
142
|
+
style: "normal" | "italic" | "oblique";
|
|
147
143
|
family: string;
|
|
148
144
|
} | {
|
|
149
145
|
variationAxes: Partial<Record<"wght" | "wdth" | "slnt" | "opsz" | "ital" | "GRAD" | "XTRA" | "XOPQ" | "YOPQ" | "YTLC" | "YTUC" | "YTAS" | "YTDE" | "YTFI", {
|
|
150
|
-
name: string;
|
|
151
146
|
min: number;
|
|
152
|
-
default: number;
|
|
153
147
|
max: number;
|
|
148
|
+
name: string;
|
|
149
|
+
default: number;
|
|
154
150
|
}>>;
|
|
155
151
|
family: string;
|
|
156
152
|
} | undefined);
|
|
157
|
-
} | {
|
|
158
|
-
name: string;
|
|
159
|
-
type: "image";
|
|
160
|
-
format: string;
|
|
161
|
-
id: string;
|
|
162
|
-
projectId: string;
|
|
163
153
|
size: number;
|
|
164
154
|
description: string | null;
|
|
155
|
+
format: "ttf" | "woff" | "woff2" | "otf";
|
|
156
|
+
projectId: string;
|
|
165
157
|
createdAt: string;
|
|
158
|
+
} | {
|
|
159
|
+
type: "image";
|
|
160
|
+
id: string;
|
|
161
|
+
name: string;
|
|
166
162
|
meta: {
|
|
167
|
-
width: number;
|
|
168
163
|
height: number;
|
|
164
|
+
width: number;
|
|
169
165
|
};
|
|
166
|
+
size: number;
|
|
167
|
+
description: string | null;
|
|
168
|
+
format: string;
|
|
169
|
+
projectId: string;
|
|
170
|
+
createdAt: string;
|
|
170
171
|
} | undefined>;
|
|
171
172
|
}) => {
|
|
172
173
|
type: "page";
|
|
@@ -193,3 +194,4 @@ export declare const usePropUrl: (instanceId: Instance["id"], name: string) => {
|
|
|
193
194
|
url: string;
|
|
194
195
|
} | undefined;
|
|
195
196
|
export declare const getInstanceIdFromComponentProps: (props: Record<string, unknown>) => string;
|
|
197
|
+
export declare const getIndexWithinAncestorFromComponentProps: (props: Record<string, unknown>) => string | undefined;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { type
|
|
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";
|
|
5
5
|
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
|
-
import type {
|
|
9
|
-
|
|
8
|
+
import type { WebstudioComponentProps } from "./webstudio-component";
|
|
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;
|
|
@@ -24,9 +25,11 @@ export declare const createElementsTree: ({ renderer, imageBaseUrl, assetBaseUrl
|
|
|
24
25
|
propsByInstanceIdStore: ReadableAtom<PropsByInstanceId>;
|
|
25
26
|
assetsStore: ReadableAtom<Assets>;
|
|
26
27
|
pagesStore: ReadableAtom<Pages>;
|
|
27
|
-
executeEffectfulExpression: (expression: string, values: DataSourceValues) => DataSourceValues;
|
|
28
|
+
executeEffectfulExpression: (expression: string, args: DataSourceValues, values: DataSourceValues) => DataSourceValues;
|
|
28
29
|
dataSourceValuesStore: ReadableAtom<DataSourceValues>;
|
|
29
30
|
onDataSourceUpdate: (newValues: DataSourceValues) => void;
|
|
30
|
-
|
|
31
|
+
indexesWithinAncestors: IndexesWithinAncestors;
|
|
32
|
+
Component: ForwardRefExoticComponent<WebstudioComponentProps & RefAttributes<HTMLElement>>;
|
|
31
33
|
components: Components;
|
|
32
|
-
|
|
34
|
+
scripts?: ReactNode;
|
|
35
|
+
}) => import("react/jsx-runtime").JSX.Element | null;
|
package/lib/types/tree/root.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { type
|
|
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
|
-
import {
|
|
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
|
-
executeEffectfulExpression: (expression: string, values: DataSourceValues) => DataSourceValues;
|
|
21
|
-
Component?:
|
|
22
|
+
executeEffectfulExpression: (expression: string, args: DataSourceValues, values: DataSourceValues) => DataSourceValues;
|
|
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 {};
|
|
@@ -2,15 +2,24 @@
|
|
|
2
2
|
import type { Instance } from "@webstudio-is/project-build";
|
|
3
3
|
import type { Components } from "../components/components-utils";
|
|
4
4
|
export declare const renderWebstudioComponentChildren: (children: Array<JSX.Element | string> | undefined) => Array<JSX.Element | string | Array<JSX.Element | string>> | undefined;
|
|
5
|
-
type WebstudioComponentProps = {
|
|
5
|
+
export type WebstudioComponentProps = {
|
|
6
6
|
instance: Instance;
|
|
7
7
|
instanceSelector: Instance["id"][];
|
|
8
8
|
children: Array<JSX.Element | string>;
|
|
9
9
|
components: Components;
|
|
10
10
|
};
|
|
11
|
-
export declare const WebstudioComponent: (
|
|
12
|
-
export declare const idAttribute
|
|
13
|
-
export declare const
|
|
14
|
-
export declare const
|
|
15
|
-
export declare const
|
|
16
|
-
export
|
|
11
|
+
export declare const WebstudioComponent: import("react").ForwardRefExoticComponent<WebstudioComponentProps & import("react").RefAttributes<HTMLElement>>;
|
|
12
|
+
export declare const idAttribute: "data-ws-id";
|
|
13
|
+
export declare const selectorIdAttribute: "data-ws-selector";
|
|
14
|
+
export declare const componentAttribute: "data-ws-component";
|
|
15
|
+
export declare const showAttribute: "data-ws-show";
|
|
16
|
+
export declare const indexAttribute: "data-ws-index";
|
|
17
|
+
export declare const collapsedAttribute: "data-ws-collapsed";
|
|
18
|
+
export type WebstudioAttributes = {
|
|
19
|
+
[idAttribute]?: string | undefined;
|
|
20
|
+
[selectorIdAttribute]?: string | undefined;
|
|
21
|
+
[componentAttribute]?: string | undefined;
|
|
22
|
+
[showAttribute]?: string | undefined;
|
|
23
|
+
[collapsedAttribute]?: string | undefined;
|
|
24
|
+
};
|
|
25
|
+
export declare const splitPropsWithWebstudioAttributes: <P extends WebstudioAttributes>({ [idAttribute]: idAttributeValue, [componentAttribute]: componentAttributeValue, [showAttribute]: showAttributeValue, [collapsedAttribute]: collapsedAttributeValue, [selectorIdAttribute]: parentIdAttributeValue, ...props }: P) => [WebstudioAttributes, Omit<P, keyof WebstudioAttributes>];
|
package/package.json
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
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
|
-
"@jest/globals": "^29.6.
|
|
10
|
-
"@remix-run/react": "^1.
|
|
11
|
-
"@types/react": "^18.
|
|
12
|
-
"@types/react-dom": "^18.
|
|
13
|
-
"jest": "^29.6.
|
|
9
|
+
"@jest/globals": "^29.6.2",
|
|
10
|
+
"@remix-run/react": "^1.19.2",
|
|
11
|
+
"@types/react": "^18.2.16",
|
|
12
|
+
"@types/react-dom": "^18.2.7",
|
|
13
|
+
"jest": "^29.6.2",
|
|
14
14
|
"react": "^18.2.0",
|
|
15
15
|
"react-dom": "^18.2.0",
|
|
16
16
|
"type-fest": "^3.7.1",
|
|
17
|
-
"typescript": "5.1.
|
|
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"
|
|
@@ -29,18 +29,17 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@jsep-plugin/assignment": "^1.2.1",
|
|
31
31
|
"@nanostores/react": "^0.7.1",
|
|
32
|
-
"detect-font": "^0.1.5",
|
|
33
32
|
"html-tags": "^3.3.1",
|
|
34
33
|
"jsep": "^1.3.8",
|
|
35
34
|
"nanoevents": "^8.0.0",
|
|
36
35
|
"nanoid": "^4.0.2",
|
|
37
36
|
"nanostores": "^0.9.3",
|
|
38
|
-
"@webstudio-is/
|
|
39
|
-
"@webstudio-is/css-
|
|
40
|
-
"@webstudio-is/
|
|
41
|
-
"@webstudio-is/
|
|
42
|
-
"@webstudio-is/
|
|
43
|
-
"@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"
|
|
44
43
|
},
|
|
45
44
|
"exports": {
|
|
46
45
|
".": {
|
|
@@ -61,7 +60,7 @@
|
|
|
61
60
|
"src/*",
|
|
62
61
|
"!*.test.*"
|
|
63
62
|
],
|
|
64
|
-
"license": "
|
|
63
|
+
"license": "AGPL-3.0-or-later",
|
|
65
64
|
"private": false,
|
|
66
65
|
"sideEffects": false,
|
|
67
66
|
"scripts": {
|
|
@@ -69,7 +68,7 @@
|
|
|
69
68
|
"build": "build-package",
|
|
70
69
|
"build:args": "generate-arg-types './src/components/*.tsx ./src/app/custom-components/*.tsx !./src/**/*.stories.tsx !./src/**/*.ws.tsx' && prettier --write \"**/*.props.ts\"",
|
|
71
70
|
"dts": "tsc --project tsconfig.dts.json",
|
|
72
|
-
"typecheck": "tsc
|
|
71
|
+
"typecheck": "tsc",
|
|
73
72
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests",
|
|
74
73
|
"checks": "pnpm typecheck && pnpm test"
|
|
75
74
|
}
|
|
@@ -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
|
+
};
|
|
@@ -22,6 +22,7 @@ export const componentCategories = [
|
|
|
22
22
|
"text",
|
|
23
23
|
"media",
|
|
24
24
|
"forms",
|
|
25
|
+
"radix",
|
|
25
26
|
"hidden",
|
|
26
27
|
] as const;
|
|
27
28
|
|
|
@@ -52,7 +53,16 @@ const WsComponentMeta = z.object({
|
|
|
52
53
|
type: z.enum(["container", "control", "embed", "rich-text-child"]),
|
|
53
54
|
requiredAncestors: z.optional(z.array(z.string())),
|
|
54
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()),
|
|
55
61
|
stylable: z.optional(z.boolean()),
|
|
62
|
+
// specifies whether the instance can be deleted,
|
|
63
|
+
// copied or dragged out of its parent instance
|
|
64
|
+
// true by default
|
|
65
|
+
detachable: z.optional(z.boolean()),
|
|
56
66
|
label: z.string(),
|
|
57
67
|
description: z.string().optional(),
|
|
58
68
|
icon: z.string(),
|
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";
|
|
@@ -41,6 +42,7 @@ export const ReactSdkContext = createContext<
|
|
|
41
42
|
dataSourceValuesStore: ReadableAtom<DataSourceValues>;
|
|
42
43
|
executeEffectfulExpression: (
|
|
43
44
|
expression: string,
|
|
45
|
+
args: DataSourceValues,
|
|
44
46
|
values: DataSourceValues
|
|
45
47
|
) => DataSourceValues;
|
|
46
48
|
setDataSourceValues: (newValues: DataSourceValues) => void;
|
|
@@ -49,6 +51,7 @@ export const ReactSdkContext = createContext<
|
|
|
49
51
|
prop: Prop["name"],
|
|
50
52
|
value: unknown
|
|
51
53
|
) => void;
|
|
54
|
+
indexesWithinAncestors: IndexesWithinAncestors;
|
|
52
55
|
}
|
|
53
56
|
>({
|
|
54
57
|
imageBaseUrl: "/",
|
|
@@ -66,4 +69,5 @@ export const ReactSdkContext = createContext<
|
|
|
66
69
|
setBoundDataSourceValue: () => {
|
|
67
70
|
throw Error("React SDK setBoundDataSourceValue is not implemented");
|
|
68
71
|
},
|
|
72
|
+
indexesWithinAncestors: new Map(),
|
|
69
73
|
});
|
package/src/css/index.ts
CHANGED
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);
|