@builder.io/sdk-solid 0.0.1

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 (89) hide show
  1. package/README.md +3 -0
  2. package/package.json +9 -0
  3. package/src/blocks/button.js +41 -0
  4. package/src/blocks/button.lite.tsx +18 -0
  5. package/src/blocks/columns.js +133 -0
  6. package/src/blocks/columns.lite.tsx +96 -0
  7. package/src/blocks/custom-code.js +72 -0
  8. package/src/blocks/custom-code.lite.tsx +65 -0
  9. package/src/blocks/embed.js +62 -0
  10. package/src/blocks/embed.lite.tsx +57 -0
  11. package/src/blocks/form.js +355 -0
  12. package/src/blocks/form.lite.tsx +291 -0
  13. package/src/blocks/fragment.js +15 -0
  14. package/src/blocks/fragment.lite.tsx +3 -0
  15. package/src/blocks/image.js +136 -0
  16. package/src/blocks/image.lite.tsx +81 -0
  17. package/src/blocks/img.js +39 -0
  18. package/src/blocks/img.lite.tsx +16 -0
  19. package/src/blocks/input.js +45 -0
  20. package/src/blocks/input.lite.tsx +18 -0
  21. package/src/blocks/raw-text.js +25 -0
  22. package/src/blocks/raw-text.lite.tsx +8 -0
  23. package/src/blocks/section.js +24 -0
  24. package/src/blocks/section.lite.tsx +16 -0
  25. package/src/blocks/select.js +57 -0
  26. package/src/blocks/select.lite.tsx +23 -0
  27. package/src/blocks/submit-button.js +18 -0
  28. package/src/blocks/submit-button.lite.tsx +7 -0
  29. package/src/blocks/symbol.js +69 -0
  30. package/src/blocks/symbol.lite.tsx +37 -0
  31. package/src/blocks/text.js +15 -0
  32. package/src/blocks/text.lite.tsx +3 -0
  33. package/src/blocks/textarea.js +34 -0
  34. package/src/blocks/textarea.lite.tsx +11 -0
  35. package/src/blocks/video.js +54 -0
  36. package/src/blocks/video.lite.tsx +24 -0
  37. package/src/components/block-styles.js +3 -0
  38. package/src/components/block-styles.lite.tsx +3 -0
  39. package/src/components/error-boundary.js +3 -0
  40. package/src/components/error-boundary.lite.tsx +3 -0
  41. package/src/components/render-block.js +154 -0
  42. package/src/components/render-block.lite.tsx +108 -0
  43. package/src/components/render-blocks.js +104 -0
  44. package/src/components/render-blocks.lite.tsx +72 -0
  45. package/src/components/render-content.js +314 -0
  46. package/src/components/render-content.lite.tsx +289 -0
  47. package/src/constants/device-sizes.js +39 -0
  48. package/src/context/builder.context.js +10 -0
  49. package/src/functions/evaluate.js +28 -0
  50. package/src/functions/event-handler-name.js +7 -0
  51. package/src/functions/get-block-actions.js +23 -0
  52. package/src/functions/get-block-component-options.js +23 -0
  53. package/src/functions/get-block-properties.js +29 -0
  54. package/src/functions/get-block-styles.js +42 -0
  55. package/src/functions/get-block-tag.js +6 -0
  56. package/src/functions/get-builder-search-params/fn.test.js +13 -0
  57. package/src/functions/get-builder-search-params/index.js +22 -0
  58. package/src/functions/get-content/fn.test.js +31 -0
  59. package/src/functions/get-content/index.js +137 -0
  60. package/src/functions/get-fetch.js +12 -0
  61. package/src/functions/get-global-this.js +18 -0
  62. package/src/functions/get-processed-block.js +46 -0
  63. package/src/functions/get-processed-block.test.js +31 -0
  64. package/src/functions/get-target.js +6 -0
  65. package/src/functions/if-target.js +6 -0
  66. package/src/functions/is-browser.js +6 -0
  67. package/src/functions/is-editing.js +7 -0
  68. package/src/functions/is-iframe.js +7 -0
  69. package/src/functions/is-previewing.js +14 -0
  70. package/src/functions/is-react-native.js +6 -0
  71. package/src/functions/macro-eval.js +5 -0
  72. package/src/functions/on-change.js +27 -0
  73. package/src/functions/on-change.test.js +19 -0
  74. package/src/functions/previewing-model-name.js +11 -0
  75. package/src/functions/register-component.js +53 -0
  76. package/src/functions/register.js +29 -0
  77. package/src/functions/set-editor-settings.js +15 -0
  78. package/src/functions/set.js +11 -0
  79. package/src/functions/set.test.js +16 -0
  80. package/src/functions/track.js +22 -0
  81. package/src/functions/transform-block.js +6 -0
  82. package/src/index-helpers/blocks-exports.js +20 -0
  83. package/src/index-helpers/top-of-file.js +4 -0
  84. package/src/index.js +13 -0
  85. package/src/scripts/init-editing.js +70 -0
  86. package/src/types/builder-block.js +0 -0
  87. package/src/types/builder-content.js +0 -0
  88. package/src/types/deep-partial.js +0 -0
  89. package/src/types/typescript.js +0 -0
@@ -0,0 +1,314 @@
1
+ import { template as _$template } from "solid-js/web";
2
+ import { delegateEvents as _$delegateEvents } from "solid-js/web";
3
+ import { setAttribute as _$setAttribute } from "solid-js/web";
4
+ import { effect as _$effect } from "solid-js/web";
5
+ import { createComponent as _$createComponent } from "solid-js/web";
6
+ import { insert as _$insert } from "solid-js/web";
7
+ import { memo as _$memo } from "solid-js/web";
8
+
9
+ const _tmpl$ = /*#__PURE__*/_$template(`<style></style>`, 2),
10
+ _tmpl$2 = /*#__PURE__*/_$template(`<div></div>`, 2);
11
+
12
+ import { Show, onMount } from "solid-js";
13
+ import { Dynamic } from "solid-js/web";
14
+ import { createMutable } from "solid-js/store";
15
+ import { isBrowser } from "../functions/is-browser";
16
+ import BuilderContext from "../context/builder.context";
17
+ import { track } from "../functions/track";
18
+ import { isReactNative } from "../functions/is-react-native";
19
+ import { isEditing } from "../functions/is-editing";
20
+ import { isPreviewing } from "../functions/is-previewing";
21
+ import { previewingModelName } from "../functions/previewing-model-name";
22
+ import { getContent } from "../functions/get-content";
23
+ import { convertSearchParamsToQueryObject, getBuilderSearchParams } from "../functions/get-builder-search-params";
24
+ import RenderBlocks from "./render-blocks";
25
+ import { evaluate } from "../functions/evaluate";
26
+ import { getFetch } from "../functions/get-fetch";
27
+ export default function RenderContent(props) {
28
+ const state = createMutable({
29
+ get useContent() {
30
+ const mergedContent = { ...props.content,
31
+ ...state.overrideContent,
32
+ data: { ...props.content?.data,
33
+ ...props.data,
34
+ ...state.overrideContent?.data
35
+ }
36
+ };
37
+ return mergedContent;
38
+ },
39
+
40
+ overrideContent: null,
41
+ update: 0,
42
+ overrideState: {},
43
+
44
+ get state() {
45
+ return { ...props.content?.data?.state,
46
+ ...props.data,
47
+ ...state.overrideState
48
+ };
49
+ },
50
+
51
+ get context() {
52
+ return {};
53
+ },
54
+
55
+ getCssFromFont(font, data) {
56
+ // TODO: compute what font sizes are used and only load those.......
57
+ const family = font.family + (font.kind && !font.kind.includes("#") ? ", " + font.kind : "");
58
+ const name = family.split(",")[0];
59
+ const url = font.fileUrl ?? font?.files?.regular;
60
+ let str = "";
61
+
62
+ if (url && family && name) {
63
+ str += `
64
+ @font-face {
65
+ font-family: "${family}";
66
+ src: local("${name}"), url('${url}') format('woff2');
67
+ font-display: fallback;
68
+ font-weight: 400;
69
+ }
70
+ `.trim();
71
+ }
72
+
73
+ if (font.files) {
74
+ for (const weight in font.files) {
75
+ const isNumber = String(Number(weight)) === weight;
76
+
77
+ if (!isNumber) {
78
+ continue;
79
+ } // TODO: maybe limit number loaded
80
+
81
+
82
+ const weightUrl = font.files[weight];
83
+
84
+ if (weightUrl && weightUrl !== url) {
85
+ str += `
86
+ @font-face {
87
+ font-family: "${family}";
88
+ src: url('${weightUrl}') format('woff2');
89
+ font-display: fallback;
90
+ font-weight: ${weight};
91
+ }
92
+ `.trim();
93
+ }
94
+ }
95
+ }
96
+
97
+ return str;
98
+ },
99
+
100
+ getFontCss(data) {
101
+ // TODO: flag for this
102
+ // if (!this.builder.allowCustomFonts) {
103
+ // return '';
104
+ // }
105
+ // TODO: separate internal data from external
106
+ return data?.customFonts?.map(font => this.getCssFromFont(font, data))?.join(" ") || "";
107
+ },
108
+
109
+ processMessage(event) {
110
+ const {
111
+ data
112
+ } = event;
113
+
114
+ if (data) {
115
+ switch (data.type) {
116
+ case "builder.contentUpdate":
117
+ {
118
+ const messageContent = data.data;
119
+ const key = messageContent.key || messageContent.alias || messageContent.entry || messageContent.modelName;
120
+ const contentData = messageContent.data;
121
+
122
+ if (key === props.model) {
123
+ state.overrideContent = contentData;
124
+ }
125
+
126
+ break;
127
+ }
128
+
129
+ case "builder.patchUpdates":
130
+ {
131
+ // TODO
132
+ break;
133
+ }
134
+ }
135
+ }
136
+ },
137
+
138
+ evaluateJsCode() {
139
+ // run any dynamic JS code attached to content
140
+ const jsCode = state.useContent?.data?.jsCode;
141
+
142
+ if (jsCode) {
143
+ evaluate({
144
+ code: jsCode,
145
+ context: state.context,
146
+ state: state.state
147
+ });
148
+ }
149
+ },
150
+
151
+ get httpReqsData() {
152
+ return {};
153
+ },
154
+
155
+ evalExpression(expression) {
156
+ return expression.replace(/{{([^}]+)}}/g, (_match, group) => evaluate({
157
+ code: group,
158
+ context: state.context,
159
+ state: state.state
160
+ }));
161
+ },
162
+
163
+ handleRequest({
164
+ url,
165
+ key
166
+ }) {
167
+ const fetchAndSetState = async () => {
168
+ const response = await getFetch()(url);
169
+ const json = await response.json();
170
+ const newOverrideState = { ...state.overrideState,
171
+ [key]: json
172
+ };
173
+ state.overrideState = newOverrideState;
174
+ };
175
+
176
+ fetchAndSetState();
177
+ },
178
+
179
+ runHttpRequests() {
180
+ const requests = state.useContent?.data?.httpRequests ?? {};
181
+ Object.entries(requests).forEach(([key, url]) => {
182
+ if (url && (!state.httpReqsData[key] || isEditing())) {
183
+ const evaluatedUrl = state.evalExpression(url);
184
+ state.handleRequest({
185
+ url: evaluatedUrl,
186
+ key
187
+ });
188
+ }
189
+ });
190
+ },
191
+
192
+ emitStateUpdate() {
193
+ window.dispatchEvent(new CustomEvent("builder:component:stateChange", {
194
+ detail: {
195
+ state: state.state,
196
+ ref: {
197
+ name: props.model
198
+ }
199
+ }
200
+ }));
201
+ }
202
+
203
+ });
204
+ onMount(() => {
205
+ if (isBrowser()) {
206
+ if (isEditing()) {
207
+ window.addEventListener("message", state.processMessage);
208
+ window.addEventListener("builder:component:stateChangeListenerActivated", state.emitStateUpdate);
209
+ }
210
+
211
+ if (state.useContent) {
212
+ track("impression", {
213
+ contentId: state.useContent.id
214
+ });
215
+ } // override normal content in preview mode
216
+
217
+
218
+ if (isPreviewing()) {
219
+ if (props.model && previewingModelName() === props.model) {
220
+ const currentUrl = new URL(location.href);
221
+ const previewApiKey = currentUrl.searchParams.get("apiKey");
222
+
223
+ if (previewApiKey) {
224
+ getContent({
225
+ model: props.model,
226
+ apiKey: previewApiKey,
227
+ options: getBuilderSearchParams(convertSearchParamsToQueryObject(currentUrl.searchParams))
228
+ }).then(content => {
229
+ if (content) {
230
+ state.overrideContent = content;
231
+ }
232
+ });
233
+ }
234
+ }
235
+ }
236
+
237
+ state.evaluateJsCode();
238
+ state.runHttpRequests();
239
+ state.emitStateUpdate();
240
+ }
241
+ });
242
+ return _$createComponent(Dynamic, {
243
+ value: {
244
+ get content() {
245
+ return state.useContent;
246
+ },
247
+
248
+ get state() {
249
+ return state.state;
250
+ },
251
+
252
+ get context() {
253
+ return state.context;
254
+ },
255
+
256
+ get apiKey() {
257
+ return props.apiKey;
258
+ }
259
+
260
+ },
261
+
262
+ get component() {
263
+ return BuilderContext.Provider;
264
+ },
265
+
266
+ get children() {
267
+ return _$createComponent(Show, {
268
+ get when() {
269
+ return state.state.useContent;
270
+ },
271
+
272
+ get children() {
273
+ const _el$ = _tmpl$2.cloneNode(true);
274
+
275
+ _el$.$$click = event => track("click", {
276
+ contentId: state.state.useContent.id
277
+ });
278
+
279
+ _$insert(_el$, _$createComponent(Show, {
280
+ get when() {
281
+ return _$memo(() => !!(state.state.useContent?.data?.cssCode || state.state.useContent?.data?.customFonts?.length), true)() && !isReactNative();
282
+ },
283
+
284
+ get children() {
285
+ const _el$2 = _tmpl$.cloneNode(true);
286
+
287
+ _$insert(_el$2, () => state.state.useContent.data.cssCode, null);
288
+
289
+ _$insert(_el$2, () => state.state.getFontCss(state.state.useContent.data), null);
290
+
291
+ return _el$2;
292
+ }
293
+
294
+ }), null);
295
+
296
+ _$insert(_el$, _$createComponent(RenderBlocks, {
297
+ get blocks() {
298
+ return state.state.useContent?.data?.blocks;
299
+ }
300
+
301
+ }), null);
302
+
303
+ _$effect(() => _$setAttribute(_el$, "data-builder-content-id", state.state.useContent?.id));
304
+
305
+ return _el$;
306
+ }
307
+
308
+ });
309
+ }
310
+
311
+ });
312
+ }
313
+
314
+ _$delegateEvents(["click"]);
@@ -0,0 +1,289 @@
1
+ import { Show, onMount } from "solid-js";
2
+ import { Dynamic } from "solid-js/web";
3
+ import { createMutable } from "solid-js/store";
4
+
5
+ import { isBrowser } from "../functions/is-browser";
6
+ import BuilderContext from "../context/builder.context.lite";
7
+ import { track } from "../functions/track";
8
+ import { isReactNative } from "../functions/is-react-native";
9
+ import { isEditing } from "../functions/is-editing";
10
+ import { isPreviewing } from "../functions/is-previewing";
11
+ import { previewingModelName } from "../functions/previewing-model-name";
12
+ import { getContent } from "../functions/get-content";
13
+ import {
14
+ convertSearchParamsToQueryObject,
15
+ getBuilderSearchParams,
16
+ } from "../functions/get-builder-search-params";
17
+ import RenderBlocks from "./render-blocks.lite";
18
+ import { evaluate } from "../functions/evaluate";
19
+ import { getFetch } from "../functions/get-fetch";
20
+ import { onChange } from "../functions/on-change";
21
+ import { ifTarget } from "../functions/if-target";
22
+
23
+ export default function RenderContent(props) {
24
+ const state = createMutable({
25
+ get useContent() {
26
+ const mergedContent: BuilderContent = {
27
+ ...props.content,
28
+ ...state.overrideContent,
29
+ data: {
30
+ ...props.content?.data,
31
+ ...props.data,
32
+ ...state.overrideContent?.data,
33
+ },
34
+ };
35
+ return mergedContent;
36
+ },
37
+ overrideContent: null,
38
+ update: 0,
39
+ overrideState: {},
40
+ get state() {
41
+ return {
42
+ ...props.content?.data?.state,
43
+ ...props.data,
44
+ ...state.overrideState,
45
+ };
46
+ },
47
+ get context() {
48
+ return {} as {
49
+ [index: string]: any;
50
+ };
51
+ },
52
+ getCssFromFont(font: any, data?: any) {
53
+ // TODO: compute what font sizes are used and only load those.......
54
+ const family =
55
+ font.family +
56
+ (font.kind && !font.kind.includes("#") ? ", " + font.kind : "");
57
+ const name = family.split(",")[0];
58
+ const url = font.fileUrl ?? font?.files?.regular;
59
+ let str = "";
60
+
61
+ if (url && family && name) {
62
+ str += `
63
+ @font-face {
64
+ font-family: "${family}";
65
+ src: local("${name}"), url('${url}') format('woff2');
66
+ font-display: fallback;
67
+ font-weight: 400;
68
+ }
69
+ `.trim();
70
+ }
71
+
72
+ if (font.files) {
73
+ for (const weight in font.files) {
74
+ const isNumber = String(Number(weight)) === weight;
75
+
76
+ if (!isNumber) {
77
+ continue;
78
+ } // TODO: maybe limit number loaded
79
+
80
+ const weightUrl = font.files[weight];
81
+
82
+ if (weightUrl && weightUrl !== url) {
83
+ str += `
84
+ @font-face {
85
+ font-family: "${family}";
86
+ src: url('${weightUrl}') format('woff2');
87
+ font-display: fallback;
88
+ font-weight: ${weight};
89
+ }
90
+ `.trim();
91
+ }
92
+ }
93
+ }
94
+
95
+ return str;
96
+ },
97
+ getFontCss(data?: any) {
98
+ // TODO: flag for this
99
+ // if (!this.builder.allowCustomFonts) {
100
+ // return '';
101
+ // }
102
+ // TODO: separate internal data from external
103
+ return (
104
+ data?.customFonts
105
+ ?.map((font: any) => this.getCssFromFont(font, data))
106
+ ?.join(" ") || ""
107
+ );
108
+ },
109
+ processMessage(event: MessageEvent) {
110
+ const { data } = event;
111
+
112
+ if (data) {
113
+ switch (data.type) {
114
+ case "builder.contentUpdate": {
115
+ const messageContent = data.data;
116
+ const key =
117
+ messageContent.key ||
118
+ messageContent.alias ||
119
+ messageContent.entry ||
120
+ messageContent.modelName;
121
+ const contentData = messageContent.data;
122
+
123
+ if (key === props.model) {
124
+ state.overrideContent = contentData;
125
+ }
126
+
127
+ break;
128
+ }
129
+
130
+ case "builder.patchUpdates": {
131
+ // TODO
132
+ break;
133
+ }
134
+ }
135
+ }
136
+ },
137
+ evaluateJsCode() {
138
+ // run any dynamic JS code attached to content
139
+ const jsCode = state.useContent?.data?.jsCode;
140
+
141
+ if (jsCode) {
142
+ evaluate({
143
+ code: jsCode,
144
+ context: state.context,
145
+ state: state.state,
146
+ });
147
+ }
148
+ },
149
+ get httpReqsData() {
150
+ return {};
151
+ },
152
+ evalExpression(expression: string) {
153
+ return expression.replace(/{{([^}]+)}}/g, (_match, group) =>
154
+ evaluate({
155
+ code: group,
156
+ context: state.context,
157
+ state: state.state,
158
+ })
159
+ );
160
+ },
161
+ handleRequest({ url, key }: { key: string; url: string }) {
162
+ const fetchAndSetState = async () => {
163
+ const response = await getFetch()(url);
164
+ const json = await response.json();
165
+ const newOverrideState = { ...state.overrideState, [key]: json };
166
+ state.overrideState = newOverrideState;
167
+ };
168
+
169
+ fetchAndSetState();
170
+ },
171
+ runHttpRequests() {
172
+ const requests = state.useContent?.data?.httpRequests ?? {};
173
+ Object.entries(requests).forEach(([key, url]) => {
174
+ if (url && (!state.httpReqsData[key] || isEditing())) {
175
+ const evaluatedUrl = state.evalExpression(url);
176
+ state.handleRequest({
177
+ url: evaluatedUrl,
178
+ key,
179
+ });
180
+ }
181
+ });
182
+ },
183
+ emitStateUpdate() {
184
+ window.dispatchEvent(
185
+ new CustomEvent<BuilderComponentStateChange>(
186
+ "builder:component:stateChange",
187
+ {
188
+ detail: {
189
+ state: state.state,
190
+ ref: {
191
+ name: props.model,
192
+ },
193
+ },
194
+ }
195
+ )
196
+ );
197
+ },
198
+ });
199
+
200
+ onMount(() => {
201
+ if (isBrowser()) {
202
+ if (isEditing()) {
203
+ window.addEventListener("message", state.processMessage);
204
+ window.addEventListener(
205
+ "builder:component:stateChangeListenerActivated",
206
+ state.emitStateUpdate
207
+ );
208
+ }
209
+
210
+ if (state.useContent) {
211
+ track("impression", {
212
+ contentId: state.useContent.id,
213
+ });
214
+ } // override normal content in preview mode
215
+
216
+ if (isPreviewing()) {
217
+ if (props.model && previewingModelName() === props.model) {
218
+ const currentUrl = new URL(location.href);
219
+ const previewApiKey = currentUrl.searchParams.get("apiKey");
220
+
221
+ if (previewApiKey) {
222
+ getContent({
223
+ model: props.model,
224
+ apiKey: previewApiKey,
225
+ options: getBuilderSearchParams(
226
+ convertSearchParamsToQueryObject(currentUrl.searchParams)
227
+ ),
228
+ }).then((content) => {
229
+ if (content) {
230
+ state.overrideContent = content;
231
+ }
232
+ });
233
+ }
234
+ }
235
+ }
236
+
237
+ state.evaluateJsCode();
238
+ state.runHttpRequests();
239
+ state.emitStateUpdate();
240
+ }
241
+ });
242
+
243
+ return (
244
+ <Dynamic
245
+ value={{
246
+ get content() {
247
+ return state.useContent;
248
+ },
249
+ get state() {
250
+ return state.state;
251
+ },
252
+ get context() {
253
+ return state.context;
254
+ },
255
+ get apiKey() {
256
+ return props.apiKey;
257
+ },
258
+ }}
259
+ component={BuilderContext.Provider}
260
+ >
261
+ <Show when={state.state.useContent}>
262
+ <div
263
+ onClick={(event) =>
264
+ track("click", {
265
+ contentId: state.state.useContent.id,
266
+ })
267
+ }
268
+ data-builder-content-id={state.state.useContent?.id}
269
+ >
270
+ <Show
271
+ when={
272
+ (state.state.useContent?.data?.cssCode ||
273
+ state.state.useContent?.data?.customFonts?.length) &&
274
+ !isReactNative()
275
+ }
276
+ >
277
+ <style>
278
+ {state.state.useContent.data.cssCode}
279
+ {state.state.getFontCss(state.state.useContent.data)}
280
+ </style>
281
+ </Show>
282
+ <RenderBlocks
283
+ blocks={state.state.useContent?.data?.blocks}
284
+ ></RenderBlocks>
285
+ </div>
286
+ </Show>
287
+ </Dynamic>
288
+ );
289
+ }
@@ -0,0 +1,39 @@
1
+ const sizeNames = ["xsmall", "small", "medium", "large"];
2
+ const sizes = {
3
+ xsmall: {
4
+ min: 0,
5
+ default: 0,
6
+ max: 0
7
+ },
8
+ small: {
9
+ min: 320,
10
+ default: 321,
11
+ max: 640
12
+ },
13
+ medium: {
14
+ min: 641,
15
+ default: 642,
16
+ max: 991
17
+ },
18
+ large: {
19
+ min: 990,
20
+ default: 991,
21
+ max: 1200
22
+ },
23
+ getWidthForSize(size) {
24
+ return this[size].default;
25
+ },
26
+ getSizeForWidth(width) {
27
+ for (const size of sizeNames) {
28
+ const value = this[size];
29
+ if (width <= value.max) {
30
+ return size;
31
+ }
32
+ }
33
+ return "large";
34
+ }
35
+ };
36
+ export {
37
+ sizeNames,
38
+ sizes
39
+ };
@@ -0,0 +1,10 @@
1
+ import { createContext } from "solid-js";
2
+ var stdin_default = createContext({
3
+ content: null,
4
+ context: {},
5
+ state: {},
6
+ apiKey: null
7
+ });
8
+ export {
9
+ stdin_default as default
10
+ };
@@ -0,0 +1,28 @@
1
+ import { isBrowser } from "./is-browser";
2
+ import { isEditing } from "./is-editing";
3
+ function evaluate({
4
+ code,
5
+ context,
6
+ state,
7
+ event
8
+ }) {
9
+ if (code === "") {
10
+ console.warn("Skipping evaluation of empty code block.");
11
+ return;
12
+ }
13
+ const builder = {
14
+ isEditing: isEditing(),
15
+ isBrowser: isBrowser(),
16
+ isServer: !isBrowser()
17
+ };
18
+ const useReturn = !(code.includes(";") || code.includes(" return ") || code.trim().startsWith("return "));
19
+ const useCode = useReturn ? `return (${code});` : code;
20
+ try {
21
+ return new Function("builder", "Builder", "state", "context", "event", useCode)(builder, builder, state, context, event);
22
+ } catch (e) {
23
+ console.warn("Builder custom code error: ", e);
24
+ }
25
+ }
26
+ export {
27
+ evaluate
28
+ };
@@ -0,0 +1,7 @@
1
+ function capitalizeFirstLetter(string) {
2
+ return string.charAt(0).toUpperCase() + string.slice(1);
3
+ }
4
+ const getEventHandlerName = (key) => `on${capitalizeFirstLetter(key)}`;
5
+ export {
6
+ getEventHandlerName
7
+ };
@@ -0,0 +1,23 @@
1
+ import { evaluate } from "./evaluate";
2
+ import { getEventHandlerName } from "./event-handler-name";
3
+ function getBlockActions(options) {
4
+ var _a;
5
+ const obj = {};
6
+ const optionActions = (_a = options.block.actions) != null ? _a : {};
7
+ for (const key in optionActions) {
8
+ if (!optionActions.hasOwnProperty(key)) {
9
+ continue;
10
+ }
11
+ const value = optionActions[key];
12
+ obj[getEventHandlerName(key)] = (event) => evaluate({
13
+ code: value,
14
+ context: options.context,
15
+ state: options.state,
16
+ event
17
+ });
18
+ }
19
+ return obj;
20
+ }
21
+ export {
22
+ getBlockActions
23
+ };