@builder.io/sdk-solid 0.0.3 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/package.json +7 -2
  2. package/src/blocks/button.jsx +8 -0
  3. package/src/blocks/button.lite.tsx +11 -15
  4. package/src/blocks/{columns.js → columns.jsx} +39 -81
  5. package/src/blocks/columns.lite.tsx +28 -23
  6. package/src/blocks/{custom-code.js → custom-code.jsx} +5 -25
  7. package/src/blocks/custom-code.lite.tsx +3 -1
  8. package/src/blocks/{embed.js → embed.jsx} +5 -15
  9. package/src/blocks/embed.lite.tsx +3 -1
  10. package/src/blocks/{form.js → form.jsx} +34 -136
  11. package/src/blocks/form.lite.tsx +7 -2
  12. package/src/blocks/fragment.jsx +6 -0
  13. package/src/blocks/fragment.lite.tsx +3 -1
  14. package/src/blocks/{image.js → image.jsx} +47 -138
  15. package/src/blocks/image.lite.tsx +3 -1
  16. package/src/blocks/img.jsx +11 -0
  17. package/src/blocks/img.lite.tsx +3 -1
  18. package/src/blocks/input.jsx +8 -0
  19. package/src/blocks/input.lite.tsx +3 -1
  20. package/src/blocks/raw-text.jsx +6 -0
  21. package/src/blocks/raw-text.lite.tsx +3 -1
  22. package/src/blocks/{section.js → section.jsx} +9 -23
  23. package/src/blocks/section.lite.tsx +3 -1
  24. package/src/blocks/select.jsx +17 -0
  25. package/src/blocks/select.lite.tsx +9 -4
  26. package/src/blocks/submit-button.jsx +8 -0
  27. package/src/blocks/submit-button.lite.tsx +3 -1
  28. package/src/blocks/symbol.jsx +25 -0
  29. package/src/blocks/symbol.lite.tsx +4 -2
  30. package/src/blocks/text.jsx +6 -0
  31. package/src/blocks/text.lite.tsx +3 -1
  32. package/src/blocks/textarea.jsx +6 -0
  33. package/src/blocks/textarea.lite.tsx +3 -1
  34. package/src/blocks/video.jsx +15 -0
  35. package/src/blocks/video.lite.tsx +3 -1
  36. package/src/components/block-styles.jsx +5 -0
  37. package/src/components/block-styles.lite.tsx +3 -1
  38. package/src/components/error-boundary.jsx +5 -0
  39. package/src/components/error-boundary.lite.tsx +3 -1
  40. package/src/components/{render-block.js → render-block.jsx} +30 -70
  41. package/src/components/render-block.lite.tsx +11 -3
  42. package/src/components/render-blocks.jsx +57 -0
  43. package/src/components/render-blocks.lite.tsx +7 -4
  44. package/src/components/render-content/components/render-styles.jsx +73 -0
  45. package/src/components/render-content/components/render-styles.lite.tsx +72 -0
  46. package/src/components/render-content/render-content.jsx +210 -0
  47. package/src/components/{render-content.lite.tsx → render-content/render-content.lite.tsx} +22 -78
  48. package/src/constants/target.js +4 -0
  49. package/src/functions/if-target.js +11 -2
  50. package/src/functions/track.js +2 -2
  51. package/src/index-helpers/blocks-exports.js +1 -1
  52. package/src/scripts/init-editing.js +3 -2
  53. package/src/types/targets.js +0 -0
  54. package/src/blocks/button.js +0 -41
  55. package/src/blocks/fragment.js +0 -15
  56. package/src/blocks/img.js +0 -39
  57. package/src/blocks/input.js +0 -45
  58. package/src/blocks/raw-text.js +0 -25
  59. package/src/blocks/select.js +0 -57
  60. package/src/blocks/submit-button.js +0 -18
  61. package/src/blocks/symbol.js +0 -69
  62. package/src/blocks/text.js +0 -15
  63. package/src/blocks/textarea.js +0 -34
  64. package/src/blocks/video.js +0 -54
  65. package/src/components/block-styles.js +0 -3
  66. package/src/components/error-boundary.js +0 -3
  67. package/src/components/render-blocks.js +0 -104
  68. package/src/components/render-content.js +0 -314
  69. package/src/functions/get-target.js +0 -6
  70. package/src/functions/is-react-native.js +0 -6
@@ -1,5 +1,3 @@
1
- import { mergeProps as _$mergeProps } from "solid-js/web";
2
- import { createComponent as _$createComponent } from "solid-js/web";
3
1
  import { useContext, Show, For } from "solid-js";
4
2
  import { Dynamic } from "solid-js/web";
5
3
  import { createMutable } from "solid-js/store";
@@ -12,7 +10,8 @@ import BuilderContext from "../context/builder.context";
12
10
  import { getBlockActions } from "../functions/get-block-actions";
13
11
  import { getProcessedBlock } from "../functions/get-processed-block";
14
12
  import BlockStyles from "./block-styles";
15
- export default function RenderBlock(props) {
13
+
14
+ function RenderBlock(props) {
16
15
  const state = createMutable({
17
16
  get component() {
18
17
  const componentName = state.useBlock.component?.name;
@@ -85,70 +84,31 @@ export default function RenderBlock(props) {
85
84
 
86
85
  });
87
86
  const builderContext = useContext(BuilderContext);
88
- return _$createComponent(Show, {
89
- get when() {
90
- return !state.componentInfo?.noWrap;
91
- },
92
-
93
- get children() {
94
- return _$createComponent(Dynamic, _$mergeProps(() => state.propertiesAndActions, {
95
- get style() {
96
- return state.css;
97
- },
98
-
99
- get component() {
100
- return state.tagName;
101
- },
102
-
103
- get children() {
104
- return [_$createComponent(BlockStyles, {
105
- get block() {
106
- return state.useBlock;
107
- }
108
-
109
- }), _$createComponent(Show, {
110
- get when() {
111
- return state.componentRef;
112
- },
113
-
114
- get children() {
115
- return _$createComponent(Dynamic, _$mergeProps(() => state.componentOptions, {
116
- get builderBlock() {
117
- return state.useBlock;
118
- },
119
-
120
- get component() {
121
- return state.componentRef;
122
- },
123
-
124
- get children() {
125
- return _$createComponent(For, {
126
- get each() {
127
- return state.children;
128
- },
129
-
130
- children: (child, index) => _$createComponent(RenderBlock, {
131
- block: child
132
- })
133
- });
134
- }
135
-
136
- }));
137
- }
138
-
139
- }), _$createComponent(For, {
140
- get each() {
141
- return state.noCompRefChildren;
142
- },
143
-
144
- children: (child, index) => _$createComponent(RenderBlock, {
145
- block: child
146
- })
147
- })];
148
- }
149
-
150
- }));
151
- }
152
-
153
- });
154
- }
87
+ return <>
88
+ <Show when={!state.componentInfo?.noWrap}>
89
+ <Dynamic {...state.propertiesAndActions} style={state.css} component={state.tagName}>
90
+ <BlockStyles block={state.useBlock}></BlockStyles>
91
+ <Show when={state.componentRef}>
92
+ <Dynamic {...state.componentOptions} builderBlock={state.useBlock} component={state.componentRef}>
93
+ <For each={state.children}>
94
+ {(child, _index) => {
95
+ const index = _index();
96
+
97
+ return <RenderBlock block={child}></RenderBlock>;
98
+ }}
99
+ </For>
100
+ </Dynamic>
101
+ </Show>
102
+ <For each={state.noCompRefChildren}>
103
+ {(child, _index) => {
104
+ const index = _index();
105
+
106
+ return <RenderBlock block={child}></RenderBlock>;
107
+ }}
108
+ </For>
109
+ </Dynamic>
110
+ </Show>
111
+ </>;
112
+ }
113
+
114
+ export default RenderBlock;
@@ -12,7 +12,7 @@ import { getBlockActions } from "../functions/get-block-actions";
12
12
  import { getProcessedBlock } from "../functions/get-processed-block";
13
13
  import BlockStyles from "./block-styles.lite";
14
14
 
15
- export default function RenderBlock(props) {
15
+ function RenderBlock(props) {
16
16
  const state = createMutable({
17
17
  get component() {
18
18
  const componentName = state.useBlock.component?.name;
@@ -94,15 +94,23 @@ export default function RenderBlock(props) {
94
94
  component={state.componentRef}
95
95
  >
96
96
  <For each={state.children}>
97
- {(child, index) => <RenderBlock block={child}></RenderBlock>}
97
+ {(child, _index) => {
98
+ const index = _index();
99
+ return <RenderBlock block={child}></RenderBlock>;
100
+ }}
98
101
  </For>
99
102
  </Dynamic>
100
103
  </Show>
101
104
  <For each={state.noCompRefChildren}>
102
- {(child, index) => <RenderBlock block={child}></RenderBlock>}
105
+ {(child, _index) => {
106
+ const index = _index();
107
+ return <RenderBlock block={child}></RenderBlock>;
108
+ }}
103
109
  </For>
104
110
  </Dynamic>
105
111
  </Show>
106
112
  </>
107
113
  );
108
114
  }
115
+
116
+ export default RenderBlock;
@@ -0,0 +1,57 @@
1
+ import { Show, For } from "solid-js";
2
+ import { createMutable } from "solid-js/store";
3
+ import { css } from "solid-styled-components";
4
+ import { isEditing } from "../functions/is-editing";
5
+ import RenderBlock from "./render-block";
6
+
7
+ function RenderBlocks(props) {
8
+ const state = createMutable({
9
+ get className() {
10
+ return "builder-blocks" + (!props.blocks?.length ? " no-blocks" : "");
11
+ },
12
+
13
+ onClick() {
14
+ if (isEditing() && !props.blocks?.length) {
15
+ window.parent?.postMessage({
16
+ type: "builder.clickEmptyBlocks",
17
+ data: {
18
+ parentElementId: props.parent,
19
+ dataPath: props.path
20
+ }
21
+ }, "*");
22
+ }
23
+ },
24
+
25
+ onMouseEnter() {
26
+ if (isEditing() && !props.blocks?.length) {
27
+ window.parent?.postMessage({
28
+ type: "builder.hoverEmptyBlocks",
29
+ data: {
30
+ parentElementId: props.parent,
31
+ dataPath: props.path
32
+ }
33
+ }, "*");
34
+ }
35
+ }
36
+
37
+ });
38
+ return <div class={state.className + " " + css({
39
+ display: "flex",
40
+ flexDirection: "column",
41
+ alignItems: "stretch"
42
+ })} builder-path={props.path} builder-parent-id={props.parent} dataSet={{
43
+ class: state.className
44
+ }} onClick={event => state.onClick()} onMouseEnter={event => state.onMouseEnter()}>
45
+ <Show when={props.blocks}>
46
+ <For each={props.blocks}>
47
+ {(block, _index) => {
48
+ const index = _index();
49
+
50
+ return <RenderBlock key={block.id} block={block}></RenderBlock>;
51
+ }}
52
+ </For>
53
+ </Show>
54
+ </div>;
55
+ }
56
+
57
+ export default RenderBlocks;
@@ -6,7 +6,7 @@ import { css } from "solid-styled-components";
6
6
  import { isEditing } from "../functions/is-editing";
7
7
  import RenderBlock from "./render-block.lite";
8
8
 
9
- export default function RenderBlocks(props) {
9
+ function RenderBlocks(props) {
10
10
  const state = createMutable({
11
11
  get className() {
12
12
  return "builder-blocks" + (!props.blocks?.length ? " no-blocks" : "");
@@ -62,11 +62,14 @@ export default function RenderBlocks(props) {
62
62
  >
63
63
  <Show when={props.blocks}>
64
64
  <For each={props.blocks}>
65
- {(block, index) => (
66
- <RenderBlock key={block.id} block={block}></RenderBlock>
67
- )}
65
+ {(block, _index) => {
66
+ const index = _index();
67
+ return <RenderBlock key={block.id} block={block}></RenderBlock>;
68
+ }}
68
69
  </For>
69
70
  </Show>
70
71
  </div>
71
72
  );
72
73
  }
74
+
75
+ export default RenderBlocks;
@@ -0,0 +1,73 @@
1
+ import { createMutable } from "solid-js/store";
2
+
3
+ function RenderStyles(props) {
4
+ const state = createMutable({
5
+ getCssFromFont(font) {
6
+ // TODO: compute what font sizes are used and only load those.......
7
+ const family = font.family + (font.kind && !font.kind.includes("#") ? ", " + font.kind : "");
8
+ const name = family.split(",")[0];
9
+ const url = font.fileUrl ?? font?.files?.regular;
10
+ let str = "";
11
+
12
+ if (url && family && name) {
13
+ str += `
14
+ @font-face {
15
+ font-family: "${family}";
16
+ src: local("${name}"), url('${url}') format('woff2');
17
+ font-display: fallback;
18
+ font-weight: 400;
19
+ }
20
+ `.trim();
21
+ }
22
+
23
+ if (font.files) {
24
+ for (const weight in font.files) {
25
+ const isNumber = String(Number(weight)) === weight;
26
+
27
+ if (!isNumber) {
28
+ continue;
29
+ } // TODO: maybe limit number loaded
30
+
31
+
32
+ const weightUrl = font.files[weight];
33
+
34
+ if (weightUrl && weightUrl !== url) {
35
+ str += `
36
+ @font-face {
37
+ font-family: "${family}";
38
+ src: url('${weightUrl}') format('woff2');
39
+ font-display: fallback;
40
+ font-weight: ${weight};
41
+ }
42
+ `.trim();
43
+ }
44
+ }
45
+ }
46
+
47
+ return str;
48
+ },
49
+
50
+ getFontCss({
51
+ customFonts
52
+ }) {
53
+ // TODO: flag for this
54
+ // if (!this.builder.allowCustomFonts) {
55
+ // return '';
56
+ // }
57
+ // TODO: separate internal data from external
58
+ return customFonts?.map(font => this.getCssFromFont(font))?.join(" ") || "";
59
+ },
60
+
61
+ getInjectedStyles() {
62
+ return `
63
+ ${props.cssCode}
64
+ ${state.getFontCss({
65
+ customFonts: props.customFonts
66
+ })}`;
67
+ }
68
+
69
+ });
70
+ return <style>{state.getInjectedStyles()}</style>;
71
+ }
72
+
73
+ export default RenderStyles;
@@ -0,0 +1,72 @@
1
+ import { createMutable } from "solid-js/store";
2
+
3
+ function RenderStyles(props) {
4
+ const state = createMutable({
5
+ getCssFromFont(font: CustomFont) {
6
+ // TODO: compute what font sizes are used and only load those.......
7
+ const family =
8
+ font.family +
9
+ (font.kind && !font.kind.includes("#") ? ", " + font.kind : "");
10
+ const name = family.split(",")[0];
11
+ const url = font.fileUrl ?? font?.files?.regular;
12
+ let str = "";
13
+
14
+ if (url && family && name) {
15
+ str += `
16
+ @font-face {
17
+ font-family: "${family}";
18
+ src: local("${name}"), url('${url}') format('woff2');
19
+ font-display: fallback;
20
+ font-weight: 400;
21
+ }
22
+ `.trim();
23
+ }
24
+
25
+ if (font.files) {
26
+ for (const weight in font.files) {
27
+ const isNumber = String(Number(weight)) === weight;
28
+
29
+ if (!isNumber) {
30
+ continue;
31
+ } // TODO: maybe limit number loaded
32
+
33
+ const weightUrl = font.files[weight];
34
+
35
+ if (weightUrl && weightUrl !== url) {
36
+ str += `
37
+ @font-face {
38
+ font-family: "${family}";
39
+ src: url('${weightUrl}') format('woff2');
40
+ font-display: fallback;
41
+ font-weight: ${weight};
42
+ }
43
+ `.trim();
44
+ }
45
+ }
46
+ }
47
+
48
+ return str;
49
+ },
50
+ getFontCss({ customFonts }: { customFonts?: CustomFont[] }) {
51
+ // TODO: flag for this
52
+ // if (!this.builder.allowCustomFonts) {
53
+ // return '';
54
+ // }
55
+ // TODO: separate internal data from external
56
+ return (
57
+ customFonts?.map((font) => this.getCssFromFont(font))?.join(" ") || ""
58
+ );
59
+ },
60
+ getInjectedStyles() {
61
+ return `
62
+ ${props.cssCode}
63
+ ${state.getFontCss({
64
+ customFonts: props.customFonts,
65
+ })}`;
66
+ },
67
+ });
68
+
69
+ return <style>{state.getInjectedStyles()}</style>;
70
+ }
71
+
72
+ export default RenderStyles;
@@ -0,0 +1,210 @@
1
+ import { Show, onMount } from "solid-js";
2
+ import { Dynamic } from "solid-js/web";
3
+ import { createMutable } from "solid-js/store";
4
+ import { isBrowser } from "../../functions/is-browser";
5
+ import BuilderContext from "../../context/builder.context";
6
+ import { track } from "../../functions/track";
7
+ import { isEditing } from "../../functions/is-editing";
8
+ import { isPreviewing } from "../../functions/is-previewing";
9
+ import { previewingModelName } from "../../functions/previewing-model-name";
10
+ import { getContent } from "../../functions/get-content";
11
+ import { convertSearchParamsToQueryObject, getBuilderSearchParams } from "../../functions/get-builder-search-params";
12
+ import RenderBlocks from "../render-blocks";
13
+ import { evaluate } from "../../functions/evaluate";
14
+ import { getFetch } from "../../functions/get-fetch";
15
+ import { TARGET } from "../../constants/target";
16
+ import RenderStyles from "./components/render-styles";
17
+
18
+ function RenderContent(props) {
19
+ const state = createMutable({
20
+ get useContent() {
21
+ const mergedContent = { ...props.content,
22
+ ...state.overrideContent,
23
+ data: { ...props.content?.data,
24
+ ...props.data,
25
+ ...state.overrideContent?.data
26
+ }
27
+ };
28
+ return mergedContent;
29
+ },
30
+
31
+ overrideContent: null,
32
+ update: 0,
33
+ overrideState: {},
34
+
35
+ get state() {
36
+ return { ...props.content?.data?.state,
37
+ ...props.data,
38
+ ...state.overrideState
39
+ };
40
+ },
41
+
42
+ get context() {
43
+ return {};
44
+ },
45
+
46
+ processMessage(event) {
47
+ const {
48
+ data
49
+ } = event;
50
+
51
+ if (data) {
52
+ switch (data.type) {
53
+ case "builder.contentUpdate":
54
+ {
55
+ const messageContent = data.data;
56
+ const key = messageContent.key || messageContent.alias || messageContent.entry || messageContent.modelName;
57
+ const contentData = messageContent.data;
58
+
59
+ if (key === props.model) {
60
+ state.overrideContent = contentData;
61
+ }
62
+
63
+ break;
64
+ }
65
+
66
+ case "builder.patchUpdates":
67
+ {
68
+ // TODO
69
+ break;
70
+ }
71
+ }
72
+ }
73
+ },
74
+
75
+ evaluateJsCode() {
76
+ // run any dynamic JS code attached to content
77
+ const jsCode = state.useContent?.data?.jsCode;
78
+
79
+ if (jsCode) {
80
+ evaluate({
81
+ code: jsCode,
82
+ context: state.context,
83
+ state: state.state
84
+ });
85
+ }
86
+ },
87
+
88
+ get httpReqsData() {
89
+ return {};
90
+ },
91
+
92
+ evalExpression(expression) {
93
+ return expression.replace(/{{([^}]+)}}/g, (_match, group) => evaluate({
94
+ code: group,
95
+ context: state.context,
96
+ state: state.state
97
+ }));
98
+ },
99
+
100
+ handleRequest({
101
+ url,
102
+ key
103
+ }) {
104
+ const fetchAndSetState = async () => {
105
+ const response = await getFetch()(url);
106
+ const json = await response.json();
107
+ const newOverrideState = { ...state.overrideState,
108
+ [key]: json
109
+ };
110
+ state.overrideState = newOverrideState;
111
+ };
112
+
113
+ fetchAndSetState();
114
+ },
115
+
116
+ runHttpRequests() {
117
+ const requests = state.useContent?.data?.httpRequests ?? {};
118
+ Object.entries(requests).forEach(([key, url]) => {
119
+ if (url && (!state.httpReqsData[key] || isEditing())) {
120
+ const evaluatedUrl = state.evalExpression(url);
121
+ state.handleRequest({
122
+ url: evaluatedUrl,
123
+ key
124
+ });
125
+ }
126
+ });
127
+ },
128
+
129
+ emitStateUpdate() {
130
+ window.dispatchEvent(new CustomEvent("builder:component:stateChange", {
131
+ detail: {
132
+ state: state.state,
133
+ ref: {
134
+ name: props.model
135
+ }
136
+ }
137
+ }));
138
+ }
139
+
140
+ });
141
+ onMount(() => {
142
+ if (isBrowser()) {
143
+ if (isEditing()) {
144
+ window.addEventListener("message", state.processMessage);
145
+ window.addEventListener("builder:component:stateChangeListenerActivated", state.emitStateUpdate);
146
+ }
147
+
148
+ if (state.useContent) {
149
+ track("impression", {
150
+ contentId: state.useContent.id
151
+ });
152
+ } // override normal content in preview mode
153
+
154
+
155
+ if (isPreviewing()) {
156
+ if (props.model && previewingModelName() === props.model) {
157
+ const currentUrl = new URL(location.href);
158
+ const previewApiKey = currentUrl.searchParams.get("apiKey");
159
+
160
+ if (previewApiKey) {
161
+ getContent({
162
+ model: props.model,
163
+ apiKey: previewApiKey,
164
+ options: getBuilderSearchParams(convertSearchParamsToQueryObject(currentUrl.searchParams))
165
+ }).then(content => {
166
+ if (content) {
167
+ state.overrideContent = content;
168
+ }
169
+ });
170
+ }
171
+ }
172
+ }
173
+
174
+ state.evaluateJsCode();
175
+ state.runHttpRequests();
176
+ state.emitStateUpdate();
177
+ }
178
+ });
179
+ return <Dynamic value={{
180
+ get content() {
181
+ return state.useContent;
182
+ },
183
+
184
+ get state() {
185
+ return state.state;
186
+ },
187
+
188
+ get context() {
189
+ return state.context;
190
+ },
191
+
192
+ get apiKey() {
193
+ return props.apiKey;
194
+ }
195
+
196
+ }} component={BuilderContext.Provider}>
197
+ <Show when={state.useContent}>
198
+ <div onClick={event => track("click", {
199
+ contentId: state.useContent.id
200
+ })} data-builder-content-id={state.useContent?.id}>
201
+ <Show when={(state.useContent?.data?.cssCode || state.useContent?.data?.customFonts?.length) && TARGET !== "reactNative"}>
202
+ <RenderStyles cssCode={state.useContent.data.cssCode} customFonts={state.useContent.data.customFonts}></RenderStyles>
203
+ </Show>
204
+ <RenderBlocks blocks={state.useContent?.data?.blocks}></RenderBlocks>
205
+ </div>
206
+ </Show>
207
+ </Dynamic>;
208
+ }
209
+
210
+ export default RenderContent;