@builder.io/sdk-solid 0.0.8-14 → 0.0.8-15
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/package.json +1 -1
- package/src/components/render-block/block-styles.jsx +2 -1
- package/src/components/render-block/render-block.jsx +81 -10
- package/src/components/render-block/render-repeated-block.jsx +32 -0
- package/src/components/render-content/render-content.jsx +5 -5
- package/src/functions/convert-style-object.js +14 -0
- package/src/functions/get-block-styles.js +7 -15
- package/src/functions/get-processed-block.js +15 -8
- package/src/functions/get-processed-block.test.js +2 -1
- package/src/functions/sanitize-styles.js +5 -0
package/package.json
CHANGED
|
@@ -8,14 +8,21 @@ import { getBlockProperties } from "../../functions/get-block-properties.js";
|
|
|
8
8
|
import { getBlockStyles } from "../../functions/get-block-styles.js";
|
|
9
9
|
import { getBlockTag } from "../../functions/get-block-tag.js";
|
|
10
10
|
import { getProcessedBlock } from "../../functions/get-processed-block.js";
|
|
11
|
+
import { evaluate } from "../../functions/evaluate.js";
|
|
11
12
|
import BlockStyles from "./block-styles.jsx";
|
|
12
13
|
import { isEmptyHtmlElement } from "./render-block.helpers.js";
|
|
13
14
|
import RenderComponent from "./render-component.jsx";
|
|
15
|
+
import RenderRepeatedBlock from "./render-repeated-block.jsx";
|
|
14
16
|
|
|
15
17
|
function RenderBlock(props) {
|
|
16
18
|
const state = createMutable({
|
|
17
19
|
get component() {
|
|
18
|
-
const componentName =
|
|
20
|
+
const componentName = getProcessedBlock({
|
|
21
|
+
block: props.block,
|
|
22
|
+
state: builderContext.state,
|
|
23
|
+
context: builderContext.context,
|
|
24
|
+
evaluateBindings: false
|
|
25
|
+
}).component?.name;
|
|
19
26
|
|
|
20
27
|
if (!componentName) {
|
|
21
28
|
return null;
|
|
@@ -55,10 +62,11 @@ function RenderBlock(props) {
|
|
|
55
62
|
},
|
|
56
63
|
|
|
57
64
|
get useBlock() {
|
|
58
|
-
return getProcessedBlock({
|
|
65
|
+
return state.repeatItemData ? props.block : getProcessedBlock({
|
|
59
66
|
block: props.block,
|
|
60
67
|
state: builderContext.state,
|
|
61
|
-
context: builderContext.context
|
|
68
|
+
context: builderContext.context,
|
|
69
|
+
evaluateBindings: true
|
|
62
70
|
});
|
|
63
71
|
},
|
|
64
72
|
|
|
@@ -90,6 +98,14 @@ function RenderBlock(props) {
|
|
|
90
98
|
};
|
|
91
99
|
},
|
|
92
100
|
|
|
101
|
+
get renderComponentProps() {
|
|
102
|
+
return {
|
|
103
|
+
blockChildren: state.children,
|
|
104
|
+
componentRef: state.componentRef,
|
|
105
|
+
componentOptions: state.componentOptions
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
|
|
93
109
|
get children() {
|
|
94
110
|
// TO-DO: When should `canHaveChildren` dictate rendering?
|
|
95
111
|
// This is currently commented out because some Builder components (e.g. Box) do not have `canHaveChildren: true`,
|
|
@@ -98,28 +114,83 @@ function RenderBlock(props) {
|
|
|
98
114
|
return state.useBlock.children ?? [];
|
|
99
115
|
},
|
|
100
116
|
|
|
101
|
-
get
|
|
117
|
+
get childrenWithoutParentComponent() {
|
|
102
118
|
/**
|
|
103
119
|
* When there is no `componentRef`, there might still be children that need to be rendered. In this case,
|
|
104
|
-
* we render them outside of `componentRef
|
|
120
|
+
* we render them outside of `componentRef`.
|
|
121
|
+
* NOTE: We make sure not to render this if `repeatItemData` is non-null, because that means we are rendering an array of
|
|
122
|
+
* blocks, and the children will be repeated within those blocks.
|
|
105
123
|
*/
|
|
106
|
-
|
|
124
|
+
const shouldRenderChildrenOutsideRef = !state.componentRef && !state.repeatItemData;
|
|
125
|
+
return shouldRenderChildrenOutsideRef ? state.children : [];
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
get repeatItemData() {
|
|
129
|
+
/**
|
|
130
|
+
* we don't use `state.useBlock` here because the processing done within its logic includes evaluating the block's bindings,
|
|
131
|
+
* which will not work if there is a repeat.
|
|
132
|
+
*/
|
|
133
|
+
const {
|
|
134
|
+
repeat,
|
|
135
|
+
...blockWithoutRepeat
|
|
136
|
+
} = props.block;
|
|
137
|
+
|
|
138
|
+
if (!repeat?.collection) {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const {
|
|
143
|
+
collection,
|
|
144
|
+
itemName
|
|
145
|
+
} = repeat;
|
|
146
|
+
const itemsArray = evaluate({
|
|
147
|
+
code: collection,
|
|
148
|
+
state: builderContext.state,
|
|
149
|
+
context: builderContext.context
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
if (Array.isArray(itemsArray)) {
|
|
153
|
+
const collectionName = collection.split(".").pop();
|
|
154
|
+
const itemNameToUse = itemName || (collectionName ? collectionName + "Item" : "item");
|
|
155
|
+
const repeatArray = itemsArray.map((item, index) => ({
|
|
156
|
+
context: { ...builderContext,
|
|
157
|
+
state: { ...builderContext.state,
|
|
158
|
+
$index: index,
|
|
159
|
+
$item: item,
|
|
160
|
+
[itemNameToUse]: item,
|
|
161
|
+
[`$${itemNameToUse}Index`]: index
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
block: blockWithoutRepeat
|
|
165
|
+
}));
|
|
166
|
+
return repeatArray;
|
|
167
|
+
} else {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
107
170
|
}
|
|
108
171
|
|
|
109
172
|
});
|
|
110
173
|
const builderContext = useContext(BuilderContext);
|
|
111
|
-
return <Show fallback={<RenderComponent
|
|
174
|
+
return <Show fallback={<RenderComponent {...state.renderComponentProps}></RenderComponent>} when={state.shouldWrap}>
|
|
112
175
|
<Show fallback={<Dynamic {...state.attributes} component={state.tagName}></Dynamic>} when={!isEmptyHtmlElement(state.tagName)}>
|
|
113
176
|
<Dynamic {...state.attributes} component={state.tagName}>
|
|
114
|
-
<
|
|
115
|
-
|
|
177
|
+
<Show fallback={<RenderComponent {...state.renderComponentProps}></RenderComponent>} when={state.repeatItemData}>
|
|
178
|
+
<For each={state.repeatItemData}>
|
|
179
|
+
{(data, _index) => {
|
|
180
|
+
const index = _index();
|
|
181
|
+
|
|
182
|
+
return <RenderRepeatedBlock key={index} repeatContext={data.context} block={data.block}></RenderRepeatedBlock>;
|
|
183
|
+
}}
|
|
184
|
+
</For>
|
|
185
|
+
</Show>
|
|
186
|
+
<For each={state.childrenWithoutParentComponent}>
|
|
116
187
|
{(child, _index) => {
|
|
117
188
|
const index = _index();
|
|
118
189
|
|
|
119
190
|
return <RenderBlock key={"render-block-" + child.id} block={child}></RenderBlock>;
|
|
120
191
|
}}
|
|
121
192
|
</For>
|
|
122
|
-
<For each={state.
|
|
193
|
+
<For each={state.childrenWithoutParentComponent}>
|
|
123
194
|
{(child, _index) => {
|
|
124
195
|
const index = _index();
|
|
125
196
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Dynamic } from "solid-js/web";
|
|
2
|
+
import BuilderContext from "../../context/builder.context";
|
|
3
|
+
import RenderBlock from "./render-block.jsx";
|
|
4
|
+
|
|
5
|
+
function RenderRepeatedBlock(props) {
|
|
6
|
+
return <Dynamic value={{
|
|
7
|
+
get content() {
|
|
8
|
+
return props.repeatContext.content;
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
get state() {
|
|
12
|
+
return props.repeatContext.state;
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
get context() {
|
|
16
|
+
return props.repeatContext.context;
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
get apiKey() {
|
|
20
|
+
return props.repeatContext.apiKey;
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
get registeredComponents() {
|
|
24
|
+
return props.repeatContext.registeredComponents;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
}} component={BuilderContext.Provider}>
|
|
28
|
+
<RenderBlock block={props.block}></RenderBlock>
|
|
29
|
+
</Dynamic>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default RenderRepeatedBlock;
|
|
@@ -41,8 +41,8 @@ function RenderContent(props) {
|
|
|
41
41
|
};
|
|
42
42
|
},
|
|
43
43
|
|
|
44
|
-
get
|
|
45
|
-
return {};
|
|
44
|
+
get contextContext() {
|
|
45
|
+
return props.context || {};
|
|
46
46
|
},
|
|
47
47
|
|
|
48
48
|
get allRegisteredComponents() {
|
|
@@ -94,7 +94,7 @@ function RenderContent(props) {
|
|
|
94
94
|
if (jsCode) {
|
|
95
95
|
evaluate({
|
|
96
96
|
code: jsCode,
|
|
97
|
-
context: state.
|
|
97
|
+
context: state.contextContext,
|
|
98
98
|
state: state.contentState
|
|
99
99
|
});
|
|
100
100
|
}
|
|
@@ -107,7 +107,7 @@ function RenderContent(props) {
|
|
|
107
107
|
evalExpression(expression) {
|
|
108
108
|
return expression.replace(/{{([^}]+)}}/g, (_match, group) => evaluate({
|
|
109
109
|
code: group,
|
|
110
|
-
context: state.
|
|
110
|
+
context: state.contextContext,
|
|
111
111
|
state: state.contentState
|
|
112
112
|
}));
|
|
113
113
|
},
|
|
@@ -208,7 +208,7 @@ function RenderContent(props) {
|
|
|
208
208
|
},
|
|
209
209
|
|
|
210
210
|
get context() {
|
|
211
|
-
return state.
|
|
211
|
+
return state.contextContext;
|
|
212
212
|
},
|
|
213
213
|
|
|
214
214
|
get apiKey() {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const camelCaseToDashCase = (str = "") => str.replace(/[A-Z]/g, (match) => "-" + match.toLowerCase());
|
|
2
|
+
const convertStyleObject = (obj) => {
|
|
3
|
+
if (!obj) {
|
|
4
|
+
return obj;
|
|
5
|
+
}
|
|
6
|
+
const newObj = {};
|
|
7
|
+
for (const key in obj) {
|
|
8
|
+
newObj[camelCaseToDashCase(key)] = obj[key];
|
|
9
|
+
}
|
|
10
|
+
return newObj;
|
|
11
|
+
};
|
|
12
|
+
export {
|
|
13
|
+
convertStyleObject
|
|
14
|
+
};
|
|
@@ -14,27 +14,19 @@ var __spreadValues = (a, b) => {
|
|
|
14
14
|
}
|
|
15
15
|
return a;
|
|
16
16
|
};
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (!obj) {
|
|
21
|
-
return obj;
|
|
22
|
-
}
|
|
23
|
-
const newObj = {};
|
|
24
|
-
for (const key in obj) {
|
|
25
|
-
newObj[camelCaseToDashCase(key)] = obj[key];
|
|
26
|
-
}
|
|
27
|
-
return newObj;
|
|
28
|
-
};
|
|
17
|
+
import { getMaxWidthQueryForSize } from "../constants/device-sizes.js";
|
|
18
|
+
import { convertStyleObject } from "./convert-style-object.js";
|
|
19
|
+
import { sanitizeBlockStyles } from "./sanitize-styles.js";
|
|
29
20
|
function getBlockStyles(block) {
|
|
30
21
|
var _a, _b, _c, _d, _e;
|
|
31
|
-
const styles = __spreadValues({}, convertStyleObject((_a = block.responsiveStyles) == null ? void 0 : _a.large));
|
|
22
|
+
const styles = __spreadValues(__spreadValues({}, convertStyleObject((_a = block.responsiveStyles) == null ? void 0 : _a.large)), block.styles);
|
|
32
23
|
if ((_b = block.responsiveStyles) == null ? void 0 : _b.medium) {
|
|
33
|
-
styles[
|
|
24
|
+
styles[getMaxWidthQueryForSize("medium")] = convertStyleObject((_c = block.responsiveStyles) == null ? void 0 : _c.medium);
|
|
34
25
|
}
|
|
35
26
|
if ((_d = block.responsiveStyles) == null ? void 0 : _d.small) {
|
|
36
|
-
styles[
|
|
27
|
+
styles[getMaxWidthQueryForSize("small")] = convertStyleObject((_e = block.responsiveStyles) == null ? void 0 : _e.small);
|
|
37
28
|
}
|
|
29
|
+
sanitizeBlockStyles(styles);
|
|
38
30
|
return styles;
|
|
39
31
|
}
|
|
40
32
|
export {
|
|
@@ -20,9 +20,11 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
|
20
20
|
import { evaluate } from "./evaluate.js";
|
|
21
21
|
import { set } from "./set.js";
|
|
22
22
|
import { transformBlock } from "./transform-block.js";
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const evaluateBindings = ({
|
|
24
|
+
block,
|
|
25
|
+
context,
|
|
26
|
+
state
|
|
27
|
+
}) => {
|
|
26
28
|
if (!block.bindings) {
|
|
27
29
|
return block;
|
|
28
30
|
}
|
|
@@ -32,14 +34,19 @@ function getProcessedBlock(options) {
|
|
|
32
34
|
});
|
|
33
35
|
for (const binding in block.bindings) {
|
|
34
36
|
const expression = block.bindings[binding];
|
|
35
|
-
const value = evaluate({
|
|
36
|
-
code: expression,
|
|
37
|
-
state,
|
|
38
|
-
context
|
|
39
|
-
});
|
|
37
|
+
const value = evaluate({ code: expression, state, context });
|
|
40
38
|
set(copied, binding, value);
|
|
41
39
|
}
|
|
42
40
|
return copied;
|
|
41
|
+
};
|
|
42
|
+
function getProcessedBlock(options) {
|
|
43
|
+
const { state, context } = options;
|
|
44
|
+
const block = transformBlock(options.block);
|
|
45
|
+
if (evaluateBindings) {
|
|
46
|
+
return evaluateBindings({ block, state, context });
|
|
47
|
+
} else {
|
|
48
|
+
return block;
|
|
49
|
+
}
|
|
43
50
|
}
|
|
44
51
|
export {
|
|
45
52
|
getProcessedBlock
|
|
@@ -20,7 +20,8 @@ test("Can process bindings", () => {
|
|
|
20
20
|
const processed = getProcessedBlock({
|
|
21
21
|
block,
|
|
22
22
|
context: {},
|
|
23
|
-
state: { test: "hello" }
|
|
23
|
+
state: { test: "hello" },
|
|
24
|
+
evaluateBindings: true
|
|
24
25
|
});
|
|
25
26
|
expect(processed).not.toEqual(block);
|
|
26
27
|
expect((_a = processed.properties) == null ? void 0 : _a.foo).toEqual("baz");
|