@builder.io/sdk-react-native 0.0.1-4 → 0.0.1-40

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 (83) hide show
  1. package/package.json +6 -4
  2. package/src/blocks/button.js +73 -24
  3. package/src/blocks/button.lite.tsx +10 -14
  4. package/src/blocks/columns.js +258 -40
  5. package/src/blocks/columns.lite.tsx +7 -13
  6. package/src/blocks/custom-code.js +76 -47
  7. package/src/blocks/custom-code.lite.tsx +12 -12
  8. package/src/blocks/embed.js +69 -47
  9. package/src/blocks/embed.lite.tsx +11 -11
  10. package/src/blocks/form.js +491 -198
  11. package/src/blocks/form.lite.tsx +52 -56
  12. package/src/blocks/fragment.js +21 -0
  13. package/src/blocks/fragment.lite.tsx +10 -0
  14. package/src/blocks/image.js +89 -83
  15. package/src/blocks/image.lite.tsx +47 -14
  16. package/src/blocks/img.js +51 -28
  17. package/src/blocks/img.lite.tsx +6 -7
  18. package/src/blocks/input.js +100 -28
  19. package/src/blocks/input.lite.tsx +4 -7
  20. package/src/blocks/raw-text.js +16 -12
  21. package/src/blocks/raw-text.lite.tsx +2 -3
  22. package/src/blocks/section.js +71 -23
  23. package/src/blocks/section.lite.tsx +4 -5
  24. package/src/blocks/select.js +78 -27
  25. package/src/blocks/select.lite.tsx +8 -9
  26. package/src/blocks/submit-button.js +47 -21
  27. package/src/blocks/submit-button.lite.tsx +3 -4
  28. package/src/blocks/symbol.js +18 -16
  29. package/src/blocks/symbol.lite.tsx +5 -5
  30. package/src/blocks/text.js +85 -16
  31. package/src/blocks/text.lite.tsx +3 -4
  32. package/src/blocks/textarea.js +60 -24
  33. package/src/blocks/textarea.lite.tsx +2 -3
  34. package/src/blocks/video.js +97 -46
  35. package/src/blocks/video.lite.tsx +5 -6
  36. package/src/components/block-styles.js +5 -0
  37. package/src/components/block-styles.lite.tsx +6 -0
  38. package/src/components/error-boundary.js +27 -0
  39. package/src/components/error-boundary.lite.tsx +6 -0
  40. package/src/components/render-block.js +123 -38
  41. package/src/components/render-block.lite.tsx +70 -33
  42. package/src/components/render-blocks.js +61 -35
  43. package/src/components/render-blocks.lite.tsx +17 -14
  44. package/src/components/render-content.js +185 -36
  45. package/src/components/render-content.lite.tsx +144 -32
  46. package/src/constants/device-sizes.js +8 -11
  47. package/src/context/builder.context.js +2 -4
  48. package/src/functions/evaluate.js +18 -9
  49. package/src/functions/event-handler-name.js +6 -0
  50. package/src/functions/get-block-actions.js +13 -13
  51. package/src/functions/get-block-component-options.js +27 -4
  52. package/src/functions/get-block-properties.js +24 -16
  53. package/src/functions/get-block-styles.js +56 -9
  54. package/src/functions/get-block-tag.js +2 -4
  55. package/src/functions/get-content.js +72 -25
  56. package/src/functions/get-content.test.js +58 -0
  57. package/src/functions/get-fetch.js +11 -0
  58. package/src/functions/get-global-this.js +17 -0
  59. package/src/functions/get-processed-block.js +19 -13
  60. package/src/functions/get-processed-block.test.js +18 -14
  61. package/src/functions/get-target.js +3 -5
  62. package/src/functions/if-target.js +1 -3
  63. package/src/functions/is-browser.js +7 -5
  64. package/src/functions/is-editing.js +5 -5
  65. package/src/functions/is-iframe.js +2 -4
  66. package/src/functions/is-previewing.js +13 -0
  67. package/src/functions/is-react-native.js +2 -4
  68. package/src/functions/macro-eval.js +2 -5
  69. package/src/functions/on-change.js +4 -7
  70. package/src/functions/on-change.test.js +10 -10
  71. package/src/functions/previewing-model-name.js +10 -0
  72. package/src/functions/register-component.js +39 -27
  73. package/src/functions/register.js +28 -0
  74. package/src/functions/set-editor-settings.js +14 -0
  75. package/src/functions/set.js +14 -5
  76. package/src/functions/set.test.js +14 -14
  77. package/src/functions/track.js +6 -8
  78. package/src/functions/transform-block.js +40 -0
  79. package/src/index.js +18 -16
  80. package/src/scripts/init-editing.js +67 -29
  81. package/src/types/deep-partial.js +1 -0
  82. package/index.js +0 -11
  83. package/src/package.json +0 -18
@@ -1,30 +1,26 @@
1
- import * as React from "react";
2
- import { View, StyleSheet, Image, Text } from "react-native";
3
- import { useState, useContext, useRef } from "react";
4
- import { BuilderBlockComponent as BuilderBlock } from "@dummy";
5
- import { Builder, builder } from "@builder.io/sdk";
6
- import { BuilderBlocks } from "@dummy";
7
- import { set } from "@dummy";
8
- import { get } from "@dummy";
1
+ import * as React from 'react';
2
+ import { View, StyleSheet, Image, Text } from 'react-native';
3
+ import { useState, useRef } from 'react';
4
+ import RenderBlock from '../components/render-block.lite';
9
5
 
10
6
  export default function FormComponent(props) {
11
- const [state, setState] = useState(() => "unsubmitted");
7
+ const [state, setState] = useState(() => 'unsubmitted');
12
8
 
13
9
  const [responseData, setResponseData] = useState(() => null);
14
10
 
15
- const [formErrorMessage, setFormErrorMessage] = useState(() => "");
11
+ const [formErrorMessage, setFormErrorMessage] = useState(() => '');
16
12
 
17
13
  function submissionState() {
18
14
  return (Builder.isEditing && props.previewState) || state;
19
15
  }
20
16
 
21
17
  function onSubmit(event) {
22
- const sendWithJs = props.sendWithJs || props.sendSubmissionsTo === "email";
18
+ const sendWithJs = props.sendWithJs || props.sendSubmissionsTo === 'email';
23
19
 
24
- if (props.sendSubmissionsTo === "zapier") {
20
+ if (props.sendSubmissionsTo === 'zapier') {
25
21
  event.preventDefault();
26
22
  } else if (sendWithJs) {
27
- if (!(props.action || props.sendSubmissionsTo === "email")) {
23
+ if (!(props.action || props.sendSubmissionsTo === 'email')) {
28
24
  event.preventDefault();
29
25
  return;
30
26
  }
@@ -36,7 +32,7 @@ export default function FormComponent(props) {
36
32
  const formData = new FormData(el); // TODO: maybe support null
37
33
 
38
34
  const formPairs = Array.from(
39
- event.currentTarget.querySelectorAll("input,select,textarea")
35
+ event.currentTarget.querySelectorAll('input,select,textarea')
40
36
  )
41
37
  .filter((el) => !!el.name)
42
38
  .map((el) => {
@@ -44,7 +40,7 @@ export default function FormComponent(props) {
44
40
  const key = el.name;
45
41
 
46
42
  if (el instanceof HTMLInputElement) {
47
- if (el.type === "radio") {
43
+ if (el.type === 'radio') {
48
44
  if (el.checked) {
49
45
  value = el.name;
50
46
  return {
@@ -52,15 +48,15 @@ export default function FormComponent(props) {
52
48
  value,
53
49
  };
54
50
  }
55
- } else if (el.type === "checkbox") {
51
+ } else if (el.type === 'checkbox') {
56
52
  value = el.checked;
57
- } else if (el.type === "number" || el.type === "range") {
53
+ } else if (el.type === 'number' || el.type === 'range') {
58
54
  const num = el.valueAsNumber;
59
55
 
60
56
  if (!isNaN(num)) {
61
57
  value = num;
62
58
  }
63
- } else if (el.type === "file") {
59
+ } else if (el.type === 'file') {
64
60
  // TODO: one vs multiple files
65
61
  value = el.files;
66
62
  } else {
@@ -77,8 +73,8 @@ export default function FormComponent(props) {
77
73
  });
78
74
  let contentType = props.contentType;
79
75
 
80
- if (props.sendSubmissionsTo === "email") {
81
- contentType = "multipart/form-data";
76
+ if (props.sendSubmissionsTo === 'email') {
77
+ contentType = 'multipart/form-data';
82
78
  }
83
79
 
84
80
  Array.from(formPairs).forEach(({ value }) => {
@@ -87,13 +83,13 @@ export default function FormComponent(props) {
87
83
  (Array.isArray(value) && value[0] instanceof File) ||
88
84
  value instanceof FileList
89
85
  ) {
90
- contentType = "multipart/form-data";
86
+ contentType = 'multipart/form-data';
91
87
  }
92
88
  }); // TODO: send as urlEncoded or multipart by default
93
89
  // because of ease of use and reliability in browser API
94
90
  // for encoding the form?
95
91
 
96
- if (contentType !== "application/json") {
92
+ if (contentType !== 'application/json') {
97
93
  body = formData;
98
94
  } else {
99
95
  // Json
@@ -104,38 +100,38 @@ export default function FormComponent(props) {
104
100
  body = JSON.stringify(json);
105
101
  }
106
102
 
107
- if (contentType && contentType !== "multipart/form-data") {
103
+ if (contentType && contentType !== 'multipart/form-data') {
108
104
  if (
109
105
  /* Zapier doesn't allow content-type header to be sent from browsers */ !(
110
- sendWithJs && props.action?.includes("zapier.com")
106
+ sendWithJs && props.action?.includes('zapier.com')
111
107
  )
112
108
  ) {
113
- headers["content-type"] = contentType;
109
+ headers['content-type'] = contentType;
114
110
  }
115
111
  }
116
- const presubmitEvent = new CustomEvent("presubmit", { detail: { body } });
112
+ const presubmitEvent = new CustomEvent('presubmit', { detail: { body } });
117
113
  if (formRef.current) {
118
114
  formRef.current.dispatchEvent(presubmitEvent);
119
115
  if (presubmitEvent.defaultPrevented) {
120
116
  return;
121
117
  }
122
118
  }
123
- setState("sending");
119
+ setState('sending');
124
120
  const formUrl = `${
125
- builder.env === "dev" ? "http://localhost:5000" : "https://builder.io"
121
+ builder.env === 'dev' ? 'http://localhost:5000' : 'https://builder.io'
126
122
  }/api/v1/form-submit?apiKey=${builder.apiKey}&to=${btoa(
127
- props.sendSubmissionsToEmail || ""
128
- )}&name=${encodeURIComponent(props.name || "")}`;
123
+ props.sendSubmissionsToEmail || ''
124
+ )}&name=${encodeURIComponent(props.name || '')}`;
129
125
  fetch(
130
- props.sendSubmissionsTo === "email"
126
+ props.sendSubmissionsTo === 'email'
131
127
  ? formUrl
132
128
  : props.action /* TODO: throw error if no action URL */,
133
- { body, headers, method: props.method || "post" }
129
+ { body, headers, method: props.method || 'post' }
134
130
  ).then(
135
131
  async (res) => {
136
132
  let body;
137
- const contentType = res.headers.get("content-type");
138
- if (contentType && contentType.indexOf("application/json") !== -1) {
133
+ const contentType = res.headers.get('content-type');
134
+ if (contentType && contentType.indexOf('application/json') !== -1) {
139
135
  body = await res.json();
140
136
  } else {
141
137
  body = await res.text();
@@ -144,7 +140,7 @@ export default function FormComponent(props) {
144
140
  /* TODO: allow supplying an error formatter function */ let message =
145
141
  get(body, props.errorMessagePath);
146
142
  if (message) {
147
- if (typeof message !== "string") {
143
+ if (typeof message !== 'string') {
148
144
  /* TODO: ideally convert json to yaml so it woul dbe like error: - email has been taken */ message =
149
145
  JSON.stringify(message);
150
146
  }
@@ -152,9 +148,9 @@ export default function FormComponent(props) {
152
148
  }
153
149
  }
154
150
  setResponseData(body);
155
- setState(res.ok ? "success" : "error");
151
+ setState(res.ok ? 'success' : 'error');
156
152
  if (res.ok) {
157
- const submitSuccessEvent = new CustomEvent("submit:success", {
153
+ const submitSuccessEvent = new CustomEvent('submit:success', {
158
154
  detail: { res, body },
159
155
  });
160
156
  if (formRef.current) {
@@ -172,7 +168,7 @@ export default function FormComponent(props) {
172
168
  props.successUrl
173
169
  ) {
174
170
  if (formRef.current) {
175
- const event = new CustomEvent("route", {
171
+ const event = new CustomEvent('route', {
176
172
  detail: { url: props.successUrl },
177
173
  });
178
174
  formRef.current.dispatchEvent(event);
@@ -186,7 +182,7 @@ export default function FormComponent(props) {
186
182
  }
187
183
  },
188
184
  (err) => {
189
- const submitErrorEvent = new CustomEvent("submit:error", {
185
+ const submitErrorEvent = new CustomEvent('submit:error', {
190
186
  detail: { error: err },
191
187
  });
192
188
  if (formRef.current) {
@@ -196,7 +192,7 @@ export default function FormComponent(props) {
196
192
  }
197
193
  }
198
194
  setResponseData(err);
199
- setState("error");
195
+ setState('error');
200
196
  }
201
197
  );
202
198
  }
@@ -212,46 +208,46 @@ export default function FormComponent(props) {
212
208
  name={props.name}
213
209
  onSubmit={(event) => onSubmit(event)}
214
210
  >
215
- {" "}
216
- {props.builderBlock && props.builderBlock.children && (
211
+ {' '}
212
+ {props.builderBlock && props.builderBlock.children ? (
217
213
  <>
218
- {props.builderBlock?.children.map((block) => (
219
- <BuilderBlockComponent block={block} />
214
+ {props.builderBlock?.children?.map((block) => (
215
+ <RenderBlock block={block} />
220
216
  ))}
221
217
  </>
222
- )}{" "}
223
- {submissionState() === "error" && (
218
+ ) : null}{' '}
219
+ {submissionState() === 'error' ? (
224
220
  <>
225
221
  <BuilderBlocks dataPath="errorMessage" blocks={props.errorMessage} />
226
222
  </>
227
- )}{" "}
228
- {submissionState() === "sending" && (
223
+ ) : null}{' '}
224
+ {submissionState() === 'sending' ? (
229
225
  <>
230
226
  <BuilderBlocks
231
227
  dataPath="sendingMessage"
232
228
  blocks={props.sendingMessage}
233
229
  />
234
230
  </>
235
- )}{" "}
236
- {submissionState() === "error" && responseData && (
231
+ ) : null}{' '}
232
+ {submissionState() === 'error' && responseData ? (
237
233
  <>
238
234
  <View className="builder-form-error-text" style={styles.view1}>
239
- {" "}
240
- {JSON.stringify(responseData, null, 2)}{" "}
235
+ {' '}
236
+ <Text>{JSON.stringify(responseData, null, 2)}</Text>{' '}
241
237
  </View>
242
238
  </>
243
- )}{" "}
244
- {submissionState() === "success" && (
239
+ ) : null}{' '}
240
+ {submissionState() === 'success' ? (
245
241
  <>
246
242
  <BuilderBlocks
247
243
  dataPath="successMessage"
248
244
  blocks={props.successMessage}
249
245
  />
250
246
  </>
251
- )}{" "}
247
+ ) : null}{' '}
252
248
  </View>
253
249
  );
254
250
  }
255
251
  const styles = StyleSheet.create({
256
- view1: { padding: "10px", color: "red", textAlign: "center" },
252
+ view1: { padding: 10, color: 'red', textAlign: 'center' },
257
253
  });
@@ -0,0 +1,21 @@
1
+ import { registerComponent } from '../functions/register-component';
2
+
3
+ import * as React from 'react';
4
+ import { View, Text } from 'react-native';
5
+ function FragmentComponent(props) {
6
+ return /* @__PURE__ */ React.createElement(
7
+ View,
8
+ null,
9
+ /* @__PURE__ */ React.createElement(Text, null, props.children)
10
+ );
11
+ }
12
+ export { FragmentComponent as default };
13
+
14
+ registerComponent(FragmentComponent, {
15
+ name: 'Fragment',
16
+ static: true,
17
+ hidden: true,
18
+ builtIn: true,
19
+ canHaveChildren: true,
20
+ noWrap: true,
21
+ });
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ import { View, StyleSheet, Image, Text } from 'react-native';
3
+
4
+ export default function FragmentComponent(props) {
5
+ return (
6
+ <View>
7
+ <Text>{props.children}</Text>
8
+ </View>
9
+ );
10
+ }
@@ -1,123 +1,129 @@
1
1
  import * as React from 'react';
2
- import { Image as ReactImage, View } from "react-native";
3
- import { registerComponent } from "../functions/register-component";
2
+ import { Image as ReactImage, View } from 'react-native';
3
+ import { registerComponent } from '../functions/register-component';
4
4
  function Image(props) {
5
- return /* @__PURE__ */ React.createElement(View, {
6
- style: { position: "relative" }
7
- }, /* @__PURE__ */ React.createElement(ReactImage, {
8
- resizeMode: props.backgroundSize || "contain",
9
- style: { position: "absolute", top: 0, bottom: 0, left: 0, right: 0 },
10
- source: { uri: props.image }
11
- }), /* @__PURE__ */ React.createElement("div", {
12
- className: "builder-image-sizer",
13
- style: {
14
- width: "100%",
15
- paddingTop: props.aspectRatio * 100 + "%",
16
- pointerEvents: "none",
17
- fontSize: 0
18
- }
19
- }, " "));
5
+ return /* @__PURE__ */ React.createElement(
6
+ View,
7
+ {
8
+ style: { position: 'relative' },
9
+ },
10
+ /* @__PURE__ */ React.createElement(ReactImage, {
11
+ resizeMode: props.backgroundSize || 'contain',
12
+ style: { position: 'absolute', top: 0, bottom: 0, left: 0, right: 0 },
13
+ source: { uri: props.image },
14
+ }),
15
+ /* @__PURE__ */ React.createElement(View, {
16
+ style: {
17
+ width: '100%',
18
+ paddingTop: props.aspectRatio * 100 + '%',
19
+ },
20
+ })
21
+ );
20
22
  }
21
23
  registerComponent(Image, {
22
- name: "Image",
24
+ name: 'Image',
23
25
  static: true,
24
- image: "https://firebasestorage.googleapis.com/v0/b/builder-3b0a2.appspot.com/o/images%2Fbaseline-insert_photo-24px.svg?alt=media&token=4e5d0ef4-f5e8-4e57-b3a9-38d63a9b9dc4",
26
+ builtIn: true,
27
+ image:
28
+ 'https://firebasestorage.googleapis.com/v0/b/builder-3b0a2.appspot.com/o/images%2Fbaseline-insert_photo-24px.svg?alt=media&token=4e5d0ef4-f5e8-4e57-b3a9-38d63a9b9dc4',
25
29
  defaultStyles: {
26
- position: "relative",
27
- minHeight: "20px",
28
- minWidth: "20px",
29
- overflow: "hidden"
30
+ position: 'relative',
31
+ minHeight: '20px',
32
+ minWidth: '20px',
33
+ overflow: 'hidden',
30
34
  },
31
35
  canHaveChildren: true,
32
36
  inputs: [
33
37
  {
34
- name: "image",
35
- type: "file",
38
+ name: 'image',
39
+ type: 'file',
36
40
  bubble: true,
37
- allowedFileTypes: ["jpeg", "jpg", "png", "svg"],
41
+ allowedFileTypes: ['jpeg', 'jpg', 'png', 'svg'],
38
42
  required: true,
39
- defaultValue: "https://cdn.builder.io/api/v1/image/assets%2Fpwgjf0RoYWbdnJSbpBAjXNRMe9F2%2Ffb27a7c790324294af8be1c35fe30f4d",
40
- onChange: " const DEFAULT_ASPECT_RATIO = 0.7041; options.delete('srcset'); options.delete('noWebp'); function loadImage(url, timeout) { return new Promise((resolve, reject) => { const img = document.createElement('img'); let loaded = false; img.onload = () => { loaded = true; resolve(img); }; img.addEventListener('error', event => { console.warn('Image load failed', event.error); reject(event.error); }); img.src = url; setTimeout(() => { if (!loaded) { reject(new Error('Image load timed out')); } }, timeout); }); } function round(num) { return Math.round(num * 1000) / 1000; } const value = options.get('image'); const aspectRatio = options.get('aspectRatio'); // For SVG images - don't render as webp, keep them as SVG fetch(value) .then(res => res.blob()) .then(blob => { if (blob.type.includes('svg')) { options.set('noWebp', true); } }); if (value && (!aspectRatio || aspectRatio === DEFAULT_ASPECT_RATIO)) { return loadImage(value).then(img => { const possiblyUpdatedAspectRatio = options.get('aspectRatio'); if ( options.get('image') === value && (!possiblyUpdatedAspectRatio || possiblyUpdatedAspectRatio === DEFAULT_ASPECT_RATIO) ) { if (img.width && img.height) { options.set('aspectRatio', round(img.height / img.width)); options.set('height', img.height); options.set('width', img.width); } } }); }"
43
+ defaultValue:
44
+ 'https://cdn.builder.io/api/v1/image/assets%2Fpwgjf0RoYWbdnJSbpBAjXNRMe9F2%2Ffb27a7c790324294af8be1c35fe30f4d',
45
+ onChange:
46
+ " const DEFAULT_ASPECT_RATIO = 0.7041; options.delete('srcset'); options.delete('noWebp'); function loadImage(url, timeout) { return new Promise((resolve, reject) => { const img = document.createElement('img'); let loaded = false; img.onload = () => { loaded = true; resolve(img); }; img.addEventListener('error', event => { console.warn('Image load failed', event.error); reject(event.error); }); img.src = url; setTimeout(() => { if (!loaded) { reject(new Error('Image load timed out')); } }, timeout); }); } function round(num) { return Math.round(num * 1000) / 1000; } const value = options.get('image'); const aspectRatio = options.get('aspectRatio'); // For SVG images - don't render as webp, keep them as SVG fetch(value) .then(res => res.blob()) .then(blob => { if (blob.type.includes('svg')) { options.set('noWebp', true); } }); if (value && (!aspectRatio || aspectRatio === DEFAULT_ASPECT_RATIO)) { return loadImage(value).then(img => { const possiblyUpdatedAspectRatio = options.get('aspectRatio'); if ( options.get('image') === value && (!possiblyUpdatedAspectRatio || possiblyUpdatedAspectRatio === DEFAULT_ASPECT_RATIO) ) { if (img.width && img.height) { options.set('aspectRatio', round(img.height / img.width)); options.set('height', img.height); options.set('width', img.width); } } }); }",
41
47
  },
42
48
  {
43
- name: "backgroundSize",
44
- type: "text",
45
- defaultValue: "cover",
49
+ name: 'backgroundSize',
50
+ type: 'text',
51
+ defaultValue: 'cover',
46
52
  enum: [
47
53
  {
48
- label: "contain",
49
- value: "contain",
50
- helperText: "The image should never get cropped"
54
+ label: 'contain',
55
+ value: 'contain',
56
+ helperText: 'The image should never get cropped',
51
57
  },
52
58
  {
53
- label: "cover",
54
- value: "cover",
55
- helperText: `The image should fill it's box, cropping when needed`
56
- }
57
- ]
59
+ label: 'cover',
60
+ value: 'cover',
61
+ helperText: `The image should fill it's box, cropping when needed`,
62
+ },
63
+ ],
58
64
  },
59
65
  {
60
- name: "backgroundPosition",
61
- type: "text",
62
- defaultValue: "center",
66
+ name: 'backgroundPosition',
67
+ type: 'text',
68
+ defaultValue: 'center',
63
69
  enum: [
64
- "center",
65
- "top",
66
- "left",
67
- "right",
68
- "bottom",
69
- "top left",
70
- "top right",
71
- "bottom left",
72
- "bottom right"
73
- ]
70
+ 'center',
71
+ 'top',
72
+ 'left',
73
+ 'right',
74
+ 'bottom',
75
+ 'top left',
76
+ 'top right',
77
+ 'bottom left',
78
+ 'bottom right',
79
+ ],
74
80
  },
75
81
  {
76
- name: "altText",
77
- type: "string",
78
- helperText: "Text to display when the user has images off"
82
+ name: 'altText',
83
+ type: 'string',
84
+ helperText: 'Text to display when the user has images off',
79
85
  },
80
86
  {
81
- name: "height",
82
- type: "number",
83
- hideFromUI: true
87
+ name: 'height',
88
+ type: 'number',
89
+ hideFromUI: true,
84
90
  },
85
91
  {
86
- name: "width",
87
- type: "number",
88
- hideFromUI: true
92
+ name: 'width',
93
+ type: 'number',
94
+ hideFromUI: true,
89
95
  },
90
96
  {
91
- name: "sizes",
92
- type: "string",
93
- hideFromUI: true
97
+ name: 'sizes',
98
+ type: 'string',
99
+ hideFromUI: true,
94
100
  },
95
101
  {
96
- name: "srcset",
97
- type: "string",
98
- hideFromUI: true
102
+ name: 'srcset',
103
+ type: 'string',
104
+ hideFromUI: true,
99
105
  },
100
106
  {
101
- name: "lazy",
102
- type: "boolean",
107
+ name: 'lazy',
108
+ type: 'boolean',
103
109
  defaultValue: true,
104
- hideFromUI: true
110
+ hideFromUI: true,
105
111
  },
106
112
  {
107
- name: "fitContent",
108
- type: "boolean",
109
- helperText: "When child blocks are provided, fit to them instead of using the image's aspect ratio",
110
- defaultValue: true
113
+ name: 'fitContent',
114
+ type: 'boolean',
115
+ helperText:
116
+ "When child blocks are provided, fit to them instead of using the image's aspect ratio",
117
+ defaultValue: true,
111
118
  },
112
119
  {
113
- name: "aspectRatio",
114
- type: "number",
115
- helperText: "This is the ratio of height/width, e.g. set to 1.5 for a 300px wide and 200px tall photo. Set to 0 to not force the image to maintain it's aspect ratio",
120
+ name: 'aspectRatio',
121
+ type: 'number',
122
+ helperText:
123
+ "This is the ratio of height/width, e.g. set to 1.5 for a 300px wide and 200px tall photo. Set to 0 to not force the image to maintain it's aspect ratio",
116
124
  advanced: true,
117
- defaultValue: 0.7041
118
- }
119
- ]
125
+ defaultValue: 0.7041,
126
+ },
127
+ ],
120
128
  });
121
- export {
122
- Image as default
123
- };
129
+ export { Image as default };
@@ -1,35 +1,68 @@
1
- import * as React from "react";
2
- import { View, StyleSheet, Image, Text } from "react-native";
3
- import { useContext } from "react";
1
+ import * as React from 'react';
2
+ import { View, StyleSheet, Image, Text } from 'react-native';
4
3
 
5
4
  export default function Image(props) {
6
5
  return (
7
- <>
6
+ <View style={styles.view1}>
8
7
  <View>
9
8
  <View
10
9
  loading="lazy"
11
10
  alt={props.altText}
12
- aria-role={props.altText ? "presentation" : undefined}
13
- className={"builder-image" + (props.class ? " " + props.class : "")}
11
+ aria-role={props.altText ? 'presentation' : undefined}
12
+ style={styles.view2}
13
+ className={'builder-image' + (props.class ? ' ' + props.class : '')}
14
14
  src={props.image}
15
15
  srcset={props.srcset}
16
16
  sizes={props.sizes}
17
- style={styles.view1}
18
17
  />
19
18
 
20
19
  <View srcSet={props.srcset} />
21
20
  </View>
22
21
 
23
- {props.children}
24
- </>
22
+ {props.aspectRatio &&
23
+ !(props.fitContent && props.builderBlock?.children?.length) ? (
24
+ <View className="builder-image-sizer" style={styles.view3}>
25
+ <Text> </Text>
26
+ </View>
27
+ ) : null}
28
+
29
+ {props.builderBlock?.children?.length && props.fitContent ? (
30
+ <>
31
+ <Text>{props.children}</Text>
32
+ </>
33
+ ) : null}
34
+
35
+ {!props.fitContent ? (
36
+ <>
37
+ <View style={styles.view4}>
38
+ <Text>{props.children}</Text>
39
+ </View>
40
+ </>
41
+ ) : null}
42
+ </View>
25
43
  );
26
44
  }
27
45
 
28
46
  const styles = StyleSheet.create({
29
- view1: {
30
- opacity: "1",
31
- transition: "opacity 0.2s ease-in-out",
32
- objectFit: "cover",
33
- objectPosition: "center",
47
+ view1: { position: 'relative' },
48
+ view2: {
49
+ opacity: 1,
50
+ transition: 'opacity 0.2s ease-in-out',
51
+ position: 'absolute',
52
+ height: 100,
53
+ width: 100,
54
+ top: 0,
55
+ left: 0,
56
+ },
57
+ view3: { width: 100, pointerEvents: 'none', fontSize: 0 },
58
+ view4: {
59
+ display: 'flex',
60
+ flexDirection: 'column',
61
+ alignItems: 'stretch',
62
+ position: 'absolute',
63
+ top: 0,
64
+ left: 0,
65
+ width: 100,
66
+ height: 100,
34
67
  },
35
68
  });