@builder.io/react 7.0.0 → 8.0.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/CHANGELOG.md +29 -0
- package/dist/builder-react-lite.cjs.js +1 -1
- package/dist/builder-react-lite.cjs.js.map +1 -1
- package/dist/builder-react-lite.esm.js +1 -1
- package/dist/builder-react-lite.esm.js.map +1 -1
- package/dist/builder-react.browser.js +2 -2
- package/dist/builder-react.browser.js.map +1 -1
- package/dist/builder-react.cjs.js +1 -1
- package/dist/builder-react.cjs.js.map +1 -1
- package/dist/builder-react.es5.js +1 -1
- package/dist/builder-react.es5.js.map +1 -1
- package/dist/builder-react.unpkg.js +2 -2
- package/dist/builder-react.unpkg.js.map +1 -1
- package/dist/lib/package.json +1 -1
- package/dist/lib/src/blocks/Image.js +3 -2
- package/dist/lib/src/blocks/Image.js.map +1 -1
- package/dist/lib/src/blocks/Symbol.js +23 -2
- package/dist/lib/src/blocks/Symbol.js.map +1 -1
- package/dist/lib/src/blocks/Video.js +3 -2
- package/dist/lib/src/blocks/Video.js.map +1 -1
- package/dist/lib/src/blocks/raw/Img.js +2 -1
- package/dist/lib/src/blocks/raw/Img.js.map +1 -1
- package/dist/lib/src/components/builder-block.component.js +14 -5
- package/dist/lib/src/components/builder-block.component.js.map +1 -1
- package/dist/lib/src/components/builder-blocks.component.js +5 -1
- package/dist/lib/src/components/builder-blocks.component.js.map +1 -1
- package/dist/lib/src/constants/file-types.constant.js +72 -0
- package/dist/lib/src/constants/file-types.constant.js.map +1 -0
- package/dist/lib/src/functions/extract-localized-values.js +35 -0
- package/dist/lib/src/functions/extract-localized-values.js.map +1 -0
- package/dist/lib/src/functions/traverse.js +72 -0
- package/dist/lib/src/functions/traverse.js.map +1 -0
- package/dist/lib/src/sdk-version.js +1 -1
- package/dist/types/src/components/builder-block.component.d.ts +1 -0
- package/dist/types/src/components/builder-blocks.component.d.ts +2 -0
- package/dist/types/src/components/builder-content.component.d.ts +0 -3
- package/dist/types/src/constants/file-types.constant.d.ts +2 -0
- package/dist/types/src/functions/extract-localized-values.d.ts +2 -0
- package/dist/types/src/functions/traverse.d.ts +34 -0
- package/dist/types/src/sdk-version.d.ts +1 -1
- package/package.json +2 -2
- package/src/blocks/Image.tsx +3 -2
- package/src/blocks/Symbol.tsx +31 -3
- package/src/blocks/Video.tsx +3 -2
- package/src/blocks/raw/Img.tsx +2 -1
- package/src/components/builder-block.component.tsx +22 -3
- package/src/components/builder-blocks.component.tsx +6 -2
- package/src/constants/file-types.constant.ts +69 -0
- package/src/functions/extract-localized-values.ts +33 -0
- package/src/functions/traverse.ts +72 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-localized-values.js","sourceRoot":"","sources":["../../../../src/functions/extract-localized-values.ts"],"names":[],"mappings":";;;AAAA,uCAAsC;AAEtC,IAAM,gBAAgB,GAAG,UAAC,KAAU;IAClC,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,iCAAiC,CAAC;AACpG,CAAC,CAAC;AAEK,IAAM,uBAAuB,GAAG,UAAC,IAAyB;IAC/D,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE;QACrD,OAAO,KAAK,CAAC;KACd;IACD,IAAI,kBAAkB,GAAG,KAAK,CAAC;IAC/B,IAAA,mBAAQ,EAAC,IAAI,EAAE,UAAA,KAAK;QAClB,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE;YAC3B,kBAAkB,GAAG,IAAI,CAAC;YAC1B,OAAO;SACR;IACH,CAAC,CAAC,CAAC;IACH,OAAO,kBAAkB,CAAC;AAC5B,CAAC,CAAC;AAZW,QAAA,uBAAuB,2BAYlC;AAEK,IAAM,sBAAsB,GAAG,UAAC,IAAyB,EAAE,MAAc;IAC9E,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE;QACrD,OAAO,EAAE,CAAC;KACX;IAED,IAAA,mBAAQ,EAAC,IAAI,EAAE,UAAC,KAAK,EAAE,MAAM;;QAC3B,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE;YAC3B,MAAM,CAAC,MAAA,KAAK,CAAC,MAAM,CAAC,mCAAI,SAAS,CAAC,CAAC;SACpC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAZW,QAAA,sBAAsB,0BAYjC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.traverse = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Recursively traverses an object or array, invoking a callback on each value.
|
|
6
|
+
*
|
|
7
|
+
* @param {any} obj - The object or array to traverse. Can also handle primitives, null, or undefined.
|
|
8
|
+
* @param {TraverseCallback} callback - The function to invoke on each value. Receives the current value
|
|
9
|
+
* and an `update` function to modify the value in its parent container.
|
|
10
|
+
* @param {any} [parent=null] - The parent object or array of the current value. Used internally.
|
|
11
|
+
* @param {any} [key=null] - The key or index of the current value in its parent. Used internally.
|
|
12
|
+
* @param {WeakSet} [visited=new WeakSet()] - Tracks visited objects to handle circular references. Used internally.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Example: Doubling all numbers in an object
|
|
16
|
+
* const obj = { a: 1, b: [2, 3, { c: 4 }] };
|
|
17
|
+
* traverse(obj, (value, update) => {
|
|
18
|
+
* if (typeof value === 'number') {
|
|
19
|
+
* update(value * 2);
|
|
20
|
+
* }
|
|
21
|
+
* });
|
|
22
|
+
* console.log(obj); // { a: 2, b: [4, 6, { c: 8 }] }
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // Example: Handling circular references
|
|
26
|
+
* const obj = { a: 1 };
|
|
27
|
+
* obj.self = obj;
|
|
28
|
+
* traverse(obj, (value, update) => {
|
|
29
|
+
* if (typeof value === 'number') {
|
|
30
|
+
* update(value * 2);
|
|
31
|
+
* }
|
|
32
|
+
* });
|
|
33
|
+
* console.log(obj.a); // 2
|
|
34
|
+
*/
|
|
35
|
+
function traverse(obj, callback, parent, key, visited) {
|
|
36
|
+
if (parent === void 0) { parent = null; }
|
|
37
|
+
if (key === void 0) { key = null; }
|
|
38
|
+
if (visited === void 0) { visited = new WeakSet(); }
|
|
39
|
+
if (obj == null || typeof obj !== 'object') {
|
|
40
|
+
callback(obj, function (newValue) {
|
|
41
|
+
if (parent !== null && key !== null) {
|
|
42
|
+
parent[key] = newValue;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (visited.has(obj)) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
visited.add(obj);
|
|
51
|
+
if (Array.isArray(obj)) {
|
|
52
|
+
obj.forEach(function (item, index) {
|
|
53
|
+
var update = function (newValue) {
|
|
54
|
+
obj[index] = newValue;
|
|
55
|
+
};
|
|
56
|
+
callback(item, update);
|
|
57
|
+
traverse(item, callback, obj, index, visited);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
Object.entries(obj).forEach(function (_a) {
|
|
62
|
+
var key = _a[0], value = _a[1];
|
|
63
|
+
var update = function (newValue) {
|
|
64
|
+
obj[key] = newValue;
|
|
65
|
+
};
|
|
66
|
+
callback(value, update);
|
|
67
|
+
traverse(value, callback, obj, key, visited);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.traverse = traverse;
|
|
72
|
+
//# sourceMappingURL=traverse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traverse.js","sourceRoot":"","sources":["../../../../src/functions/traverse.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,SAAgB,QAAQ,CACtB,GAAQ,EACR,QAA0B,EAC1B,MAAkB,EAClB,GAAe,EACf,OAAuB;IAFvB,uBAAA,EAAA,aAAkB;IAClB,oBAAA,EAAA,UAAe;IACf,wBAAA,EAAA,cAAc,OAAO,EAAE;IAEvB,IAAI,GAAG,IAAI,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;QAC1C,QAAQ,CAAC,GAAG,EAAE,UAAC,QAAa;YAC1B,IAAI,MAAM,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,EAAE;gBACnC,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;aACxB;QACH,CAAC,CAAC,CAAC;QACH,OAAO;KACR;IAED,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;QACpB,OAAO;KACR;IACD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAEjB,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;QACtB,GAAG,CAAC,OAAO,CAAC,UAAC,IAAI,EAAE,KAAK;YACtB,IAAM,MAAM,GAAG,UAAC,QAAa;gBAC3B,GAAG,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC;YACxB,CAAC,CAAC;YACF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACvB,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;KACJ;SAAM;QACL,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,UAAC,EAAY;gBAAX,GAAG,QAAA,EAAE,KAAK,QAAA;YACtC,IAAM,MAAM,GAAG,UAAC,QAAa;gBAC3B,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;YACtB,CAAC,CAAC;YACF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YACxB,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;KACJ;AACH,CAAC;AAtCD,4BAsCC"}
|
|
@@ -15,10 +15,12 @@ export interface BuilderBlocksProps {
|
|
|
15
15
|
interface BuilderBlocksState {
|
|
16
16
|
}
|
|
17
17
|
export declare class BuilderBlocks extends React.Component<BuilderBlocksProps, BuilderBlocksState> {
|
|
18
|
+
hydrated: boolean;
|
|
18
19
|
get isRoot(): boolean;
|
|
19
20
|
get noBlocks(): boolean;
|
|
20
21
|
get path(): string;
|
|
21
22
|
get parentId(): any;
|
|
23
|
+
componentDidMount(): void;
|
|
22
24
|
onClickEmptyBlocks: () => void;
|
|
23
25
|
onHoverEmptyBlocks: () => void;
|
|
24
26
|
render(): JSX.Element;
|
|
@@ -57,7 +57,6 @@ export declare class BuilderContent<ContentType extends object = any> extends Re
|
|
|
57
57
|
get renderedVariantId(): any;
|
|
58
58
|
get options(): {
|
|
59
59
|
apiVersion?: "v1" | undefined;
|
|
60
|
-
apiEndpoint?: "content" | "query" | undefined;
|
|
61
60
|
fetchOptions?: object | undefined;
|
|
62
61
|
userAttributes?: import("@builder.io/sdk/dist/src/builder.class").UserAttributes | undefined;
|
|
63
62
|
url?: string | undefined;
|
|
@@ -97,7 +96,6 @@ export declare class BuilderContent<ContentType extends object = any> extends Re
|
|
|
97
96
|
} | {
|
|
98
97
|
apiVersion?: "v3" | undefined;
|
|
99
98
|
enrich?: boolean | undefined;
|
|
100
|
-
apiEndpoint?: "content" | "query" | undefined;
|
|
101
99
|
fetchOptions?: object | undefined;
|
|
102
100
|
userAttributes?: import("@builder.io/sdk/dist/src/builder.class").UserAttributes | undefined;
|
|
103
101
|
url?: string | undefined;
|
|
@@ -137,7 +135,6 @@ export declare class BuilderContent<ContentType extends object = any> extends Re
|
|
|
137
135
|
} | {
|
|
138
136
|
apiVersion?: undefined;
|
|
139
137
|
enrich?: boolean | undefined;
|
|
140
|
-
apiEndpoint?: "content" | "query" | undefined;
|
|
141
138
|
fetchOptions?: object | undefined;
|
|
142
139
|
userAttributes?: import("@builder.io/sdk/dist/src/builder.class").UserAttributes | undefined;
|
|
143
140
|
url?: string | undefined;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
type TraverseCallback = (value: any, update: (newValue: any) => void) => void;
|
|
2
|
+
/**
|
|
3
|
+
* Recursively traverses an object or array, invoking a callback on each value.
|
|
4
|
+
*
|
|
5
|
+
* @param {any} obj - The object or array to traverse. Can also handle primitives, null, or undefined.
|
|
6
|
+
* @param {TraverseCallback} callback - The function to invoke on each value. Receives the current value
|
|
7
|
+
* and an `update` function to modify the value in its parent container.
|
|
8
|
+
* @param {any} [parent=null] - The parent object or array of the current value. Used internally.
|
|
9
|
+
* @param {any} [key=null] - The key or index of the current value in its parent. Used internally.
|
|
10
|
+
* @param {WeakSet} [visited=new WeakSet()] - Tracks visited objects to handle circular references. Used internally.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* // Example: Doubling all numbers in an object
|
|
14
|
+
* const obj = { a: 1, b: [2, 3, { c: 4 }] };
|
|
15
|
+
* traverse(obj, (value, update) => {
|
|
16
|
+
* if (typeof value === 'number') {
|
|
17
|
+
* update(value * 2);
|
|
18
|
+
* }
|
|
19
|
+
* });
|
|
20
|
+
* console.log(obj); // { a: 2, b: [4, 6, { c: 8 }] }
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // Example: Handling circular references
|
|
24
|
+
* const obj = { a: 1 };
|
|
25
|
+
* obj.self = obj;
|
|
26
|
+
* traverse(obj, (value, update) => {
|
|
27
|
+
* if (typeof value === 'number') {
|
|
28
|
+
* update(value * 2);
|
|
29
|
+
* }
|
|
30
|
+
* });
|
|
31
|
+
* console.log(obj.a); // 2
|
|
32
|
+
*/
|
|
33
|
+
export declare function traverse(obj: any, callback: TraverseCallback, parent?: any, key?: any, visited?: WeakSet<object>): void;
|
|
34
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "
|
|
1
|
+
export declare const SDK_VERSION = "8.0.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@builder.io/react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"main": "dist/builder-react.cjs.js",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"react-dom": ">=16.8.0 || ^19.0.0-rc"
|
|
98
98
|
},
|
|
99
99
|
"dependencies": {
|
|
100
|
-
"@builder.io/sdk": "
|
|
100
|
+
"@builder.io/sdk": "6.0.0",
|
|
101
101
|
"@emotion/core": "^10.0.17",
|
|
102
102
|
"hash-sum": "^2.0.0",
|
|
103
103
|
"isolated-vm": "^5.0.0",
|
package/src/blocks/Image.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import { BuilderMetaContext } from '../store/builder-meta';
|
|
|
8
8
|
import { withBuilder } from '../functions/with-builder';
|
|
9
9
|
import { throttle } from '../functions/throttle';
|
|
10
10
|
import { Breakpoints, getSizesForBreakpoints } from '../constants/device-sizes.constant';
|
|
11
|
+
import { IMAGE_FILE_TYPES } from 'src/constants/file-types.constant';
|
|
11
12
|
|
|
12
13
|
// Taken from (and modified) the shopify theme script repo
|
|
13
14
|
// https://github.com/Shopify/theme-scripts/blob/bcfb471f2a57d439e2f964a1bb65b67708cc90c3/packages/theme-images/images.js#L59
|
|
@@ -262,7 +263,7 @@ class ImageComponent extends React.Component<any, { imageLoaded: boolean; load:
|
|
|
262
263
|
|
|
263
264
|
getSrcSet(): string | undefined {
|
|
264
265
|
const url = this.image;
|
|
265
|
-
if (!url) {
|
|
266
|
+
if (!url || typeof url !== 'string') {
|
|
266
267
|
return;
|
|
267
268
|
}
|
|
268
269
|
|
|
@@ -442,7 +443,7 @@ export const Image = withBuilder(ImageComponent, {
|
|
|
442
443
|
name: 'image',
|
|
443
444
|
type: 'file',
|
|
444
445
|
bubble: true,
|
|
445
|
-
allowedFileTypes:
|
|
446
|
+
allowedFileTypes: IMAGE_FILE_TYPES,
|
|
446
447
|
required: true,
|
|
447
448
|
defaultValue:
|
|
448
449
|
'https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F72c80f114dc149019051b6852a9e3b7a',
|
package/src/blocks/Symbol.tsx
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx } from '@emotion/core';
|
|
3
3
|
import React, { PropsWithChildren } from 'react';
|
|
4
4
|
import { BuilderComponent } from '../components/builder-component.component';
|
|
5
|
-
import { Builder, BuilderElement } from '@builder.io/sdk';
|
|
5
|
+
import { Builder, BuilderElement, builder } from '@builder.io/sdk';
|
|
6
6
|
import hash from 'hash-sum';
|
|
7
7
|
import { NoWrap } from '../components/no-wrap';
|
|
8
8
|
import { BuilderStoreContext } from '../store/builder-store';
|
|
@@ -50,6 +50,7 @@ export interface SymbolProps {
|
|
|
50
50
|
class SymbolComponent extends React.Component<PropsWithChildren<SymbolProps>> {
|
|
51
51
|
ref: BuilderComponent | null = null;
|
|
52
52
|
staticRef: HTMLDivElement | null = null;
|
|
53
|
+
isEditingThisSymbol = false;
|
|
53
54
|
|
|
54
55
|
get placeholder() {
|
|
55
56
|
return (
|
|
@@ -64,6 +65,16 @@ class SymbolComponent extends React.Component<PropsWithChildren<SymbolProps>> {
|
|
|
64
65
|
if (this.useStatic && this.staticRef && refs[this.props.builderBlock?.id!]) {
|
|
65
66
|
this.staticRef.parentNode?.replaceChild(refs[this.props.builderBlock?.id!], this.staticRef);
|
|
66
67
|
}
|
|
68
|
+
Builder.nextTick(() => {
|
|
69
|
+
const { model, entry } = this.props.symbol || {};
|
|
70
|
+
// allows editing of symbols in the context of a parent page
|
|
71
|
+
this.isEditingThisSymbol = Boolean(
|
|
72
|
+
Builder.isEditing &&
|
|
73
|
+
model === builder.editingModel &&
|
|
74
|
+
entry &&
|
|
75
|
+
location.search.includes(`overrides.${entry}`)
|
|
76
|
+
);
|
|
77
|
+
});
|
|
67
78
|
}
|
|
68
79
|
|
|
69
80
|
get useStatic() {
|
|
@@ -97,6 +108,10 @@ class SymbolComponent extends React.Component<PropsWithChildren<SymbolProps>> {
|
|
|
97
108
|
showPlaceholder = true;
|
|
98
109
|
}
|
|
99
110
|
|
|
111
|
+
if (this.isEditingThisSymbol) {
|
|
112
|
+
showPlaceholder = false;
|
|
113
|
+
}
|
|
114
|
+
|
|
100
115
|
let key = dynamic ? undefined : [model, entry].join(':');
|
|
101
116
|
const dataString = Builder.isEditing ? null : data && size(data) && hash(data);
|
|
102
117
|
|
|
@@ -105,7 +120,9 @@ class SymbolComponent extends React.Component<PropsWithChildren<SymbolProps>> {
|
|
|
105
120
|
}
|
|
106
121
|
const attributes = this.props.attributes || {};
|
|
107
122
|
return (
|
|
108
|
-
<BuilderStoreContext.Consumer
|
|
123
|
+
<BuilderStoreContext.Consumer
|
|
124
|
+
key={(model || 'no model') + ':' + (entry || 'no entry' + this.isEditingThisSymbol)}
|
|
125
|
+
>
|
|
109
126
|
{state => {
|
|
110
127
|
const builderComponentKey = `${key}_${state?.state?.locale || 'Default'}`;
|
|
111
128
|
return (
|
|
@@ -139,7 +156,18 @@ class SymbolComponent extends React.Component<PropsWithChildren<SymbolProps>> {
|
|
|
139
156
|
inlineContent={symbol?.inline}
|
|
140
157
|
{...(content && { content })}
|
|
141
158
|
key={builderComponentKey}
|
|
142
|
-
options={{
|
|
159
|
+
options={{
|
|
160
|
+
...(!this.isEditingThisSymbol && {
|
|
161
|
+
key: builderComponentKey,
|
|
162
|
+
noEditorUpdates: true,
|
|
163
|
+
}),
|
|
164
|
+
...(Builder.singletonInstance.apiEndpoint === 'content' &&
|
|
165
|
+
entry && {
|
|
166
|
+
query: {
|
|
167
|
+
id: entry,
|
|
168
|
+
},
|
|
169
|
+
}),
|
|
170
|
+
}}
|
|
143
171
|
codegen={!!content?.data?.blocksJs}
|
|
144
172
|
hydrate={state.state?._hydrate}
|
|
145
173
|
builderBlock={this.props.builderBlock}
|
package/src/blocks/Video.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import React, { PropsWithChildren } from 'react';
|
|
|
5
5
|
import { throttle } from '../functions/throttle';
|
|
6
6
|
import { withChildren } from '../functions/with-children';
|
|
7
7
|
import { Builder } from '@builder.io/sdk';
|
|
8
|
+
import { IMAGE_FILE_TYPES, VIDEO_FILE_TYPES } from 'src/constants/file-types.constant';
|
|
8
9
|
|
|
9
10
|
const DEFAULT_ASPECT_RATIO = 0.7004048582995948;
|
|
10
11
|
|
|
@@ -195,7 +196,7 @@ export const Video = Builder.registerComponent(withChildren(VideoComponent), {
|
|
|
195
196
|
{
|
|
196
197
|
name: 'video',
|
|
197
198
|
type: 'file',
|
|
198
|
-
allowedFileTypes:
|
|
199
|
+
allowedFileTypes: VIDEO_FILE_TYPES,
|
|
199
200
|
bubble: true,
|
|
200
201
|
defaultValue:
|
|
201
202
|
'https://cdn.builder.io/o/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fd27731a526464deba0016216f5f9e570%2Fcompressed?apiKey=YJIGb4i01jvw0SRdL5Bt&token=d27731a526464deba0016216f5f9e570&alt=media&optimized=true',
|
|
@@ -204,7 +205,7 @@ export const Video = Builder.registerComponent(withChildren(VideoComponent), {
|
|
|
204
205
|
{
|
|
205
206
|
name: 'posterImage',
|
|
206
207
|
type: 'file',
|
|
207
|
-
allowedFileTypes:
|
|
208
|
+
allowedFileTypes: IMAGE_FILE_TYPES,
|
|
208
209
|
helperText: 'Image to show before the video plays',
|
|
209
210
|
},
|
|
210
211
|
{
|
package/src/blocks/raw/Img.tsx
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { BuilderElement } from '@builder.io/sdk';
|
|
4
4
|
import { withBuilder } from '../../functions/with-builder';
|
|
5
|
+
import { IMAGE_FILE_TYPES } from 'src/constants/file-types.constant';
|
|
5
6
|
|
|
6
7
|
export interface ImgProps {
|
|
7
8
|
attributes?: any;
|
|
@@ -36,7 +37,7 @@ export const Img = withBuilder(ImgComponent, {
|
|
|
36
37
|
name: 'image',
|
|
37
38
|
bubble: true,
|
|
38
39
|
type: 'file',
|
|
39
|
-
allowedFileTypes:
|
|
40
|
+
allowedFileTypes: IMAGE_FILE_TYPES,
|
|
40
41
|
required: true,
|
|
41
42
|
},
|
|
42
43
|
],
|
|
@@ -11,6 +11,10 @@ import { applyPatchWithMinimalMutationChain } from '../functions/apply-patch-wit
|
|
|
11
11
|
import { blockToHtmlString } from '../functions/block-to-html-string';
|
|
12
12
|
import { Link } from './Link';
|
|
13
13
|
import { fastClone } from '../functions/utils';
|
|
14
|
+
import {
|
|
15
|
+
containsLocalizedValues,
|
|
16
|
+
extractLocalizedValues,
|
|
17
|
+
} from 'src/functions/extract-localized-values';
|
|
14
18
|
|
|
15
19
|
const camelCaseToKebabCase = (str?: string) =>
|
|
16
20
|
str ? str.replace(/([A-Z])/g, g => `-${g[0].toLowerCase()}`) : '';
|
|
@@ -124,6 +128,8 @@ export class BuilderBlock extends React.Component<
|
|
|
124
128
|
private _errors?: Error[];
|
|
125
129
|
private _logs?: string[];
|
|
126
130
|
|
|
131
|
+
hydrated = false;
|
|
132
|
+
|
|
127
133
|
state = {
|
|
128
134
|
hasError: false,
|
|
129
135
|
updates: 0,
|
|
@@ -283,6 +289,7 @@ export class BuilderBlock extends React.Component<
|
|
|
283
289
|
};
|
|
284
290
|
|
|
285
291
|
componentDidMount() {
|
|
292
|
+
this.hydrated = true;
|
|
286
293
|
const block = this.block;
|
|
287
294
|
const animations = block && block.animations;
|
|
288
295
|
|
|
@@ -474,11 +481,23 @@ export class BuilderBlock extends React.Component<
|
|
|
474
481
|
}
|
|
475
482
|
}
|
|
476
483
|
|
|
477
|
-
|
|
484
|
+
let innerComponentProperties = (options.component || options.options) && {
|
|
478
485
|
...options.options,
|
|
479
486
|
...(options.component.options || options.component.data),
|
|
480
487
|
};
|
|
481
488
|
|
|
489
|
+
if (containsLocalizedValues(innerComponentProperties)) {
|
|
490
|
+
if (!this.privateState.state.locale) {
|
|
491
|
+
console.warn(
|
|
492
|
+
'[Builder.io] In order to use localized fields in Builder, you must pass a locale prop to the BuilderComponent or to options object while fetching the content to resolve localized fields. Learn more: https://www.builder.io/c/docs/localization-inline#targeting-and-inline-localization'
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
innerComponentProperties = extractLocalizedValues(
|
|
496
|
+
innerComponentProperties,
|
|
497
|
+
this.privateState.state.locale ?? 'Default'
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
|
|
482
501
|
const isVoid = voidElements.has(TagName);
|
|
483
502
|
|
|
484
503
|
const noWrap = componentInfo && (componentInfo.fragment || componentInfo.noWrap);
|
|
@@ -521,7 +540,7 @@ export class BuilderBlock extends React.Component<
|
|
|
521
540
|
: ''
|
|
522
541
|
}` +
|
|
523
542
|
(options.class ? ' ' + options.class : '') +
|
|
524
|
-
(Builder.isEditing && this.privateState.state._spacer?.parent === block.id
|
|
543
|
+
(this.hydrated && Builder.isEditing && this.privateState.state._spacer?.parent === block.id
|
|
525
544
|
? ' builder-spacer-parent'
|
|
526
545
|
: ''),
|
|
527
546
|
key: this.id + index,
|
|
@@ -541,7 +560,7 @@ export class BuilderBlock extends React.Component<
|
|
|
541
560
|
// tslint:disable-next-line:comment-format
|
|
542
561
|
///REACT15ONLY finalOptions.className = finalOptions.class
|
|
543
562
|
|
|
544
|
-
if (Builder.isEditing) {
|
|
563
|
+
if (Builder.isEditing && this.hydrated) {
|
|
545
564
|
// TODO: removed bc JS can add styles inline too?
|
|
546
565
|
(finalOptions as any)['builder-inline-styles'] = !(options.attr && options.attr.style)
|
|
547
566
|
? ''
|
|
@@ -29,6 +29,7 @@ interface BuilderBlocksState {
|
|
|
29
29
|
|
|
30
30
|
// TODO: options to set direciotn
|
|
31
31
|
export class BuilderBlocks extends React.Component<BuilderBlocksProps, BuilderBlocksState> {
|
|
32
|
+
hydrated = false;
|
|
32
33
|
get isRoot() {
|
|
33
34
|
return !this.props.child;
|
|
34
35
|
}
|
|
@@ -58,6 +59,10 @@ export class BuilderBlocks extends React.Component<BuilderBlocksProps, BuilderBl
|
|
|
58
59
|
return this.props.parent && this.props.parent.id;
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
componentDidMount() {
|
|
63
|
+
this.hydrated = true;
|
|
64
|
+
}
|
|
65
|
+
|
|
61
66
|
onClickEmptyBlocks = () => {
|
|
62
67
|
if (Builder.isIframe && this.noBlocks) {
|
|
63
68
|
window.parent?.postMessage(
|
|
@@ -105,8 +110,7 @@ export class BuilderBlocks extends React.Component<BuilderBlocksProps, BuilderBl
|
|
|
105
110
|
(this.props.className ? ' ' + this.props.className : '')
|
|
106
111
|
}
|
|
107
112
|
builder-type="blocks"
|
|
108
|
-
|
|
109
|
-
builder-path={Builder.isIframe ? this.path : undefined}
|
|
113
|
+
builder-path={Builder.isIframe && this.hydrated ? this.path : undefined}
|
|
110
114
|
builder-parent-id={this.parentId}
|
|
111
115
|
css={
|
|
112
116
|
{
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export const IMAGE_FILE_TYPES = [
|
|
2
|
+
'jpeg',
|
|
3
|
+
'jpg',
|
|
4
|
+
'png',
|
|
5
|
+
'svg',
|
|
6
|
+
'webp',
|
|
7
|
+
'gif',
|
|
8
|
+
'jfif',
|
|
9
|
+
'pjpeg',
|
|
10
|
+
'pjp',
|
|
11
|
+
'apng',
|
|
12
|
+
'avif',
|
|
13
|
+
'tif',
|
|
14
|
+
'tiff',
|
|
15
|
+
'heif',
|
|
16
|
+
'bmp',
|
|
17
|
+
'eps',
|
|
18
|
+
'raw',
|
|
19
|
+
'cr2',
|
|
20
|
+
'nef',
|
|
21
|
+
'orf',
|
|
22
|
+
'sr2',
|
|
23
|
+
'psd',
|
|
24
|
+
'heic',
|
|
25
|
+
'dib',
|
|
26
|
+
'ai',
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
export const VIDEO_FILE_TYPES = [
|
|
30
|
+
'mp4',
|
|
31
|
+
'webm',
|
|
32
|
+
'mkv',
|
|
33
|
+
'flv',
|
|
34
|
+
'vob',
|
|
35
|
+
'ogv',
|
|
36
|
+
'ogg',
|
|
37
|
+
'drc',
|
|
38
|
+
'gif',
|
|
39
|
+
'gifv',
|
|
40
|
+
'mng',
|
|
41
|
+
'avi',
|
|
42
|
+
'mov',
|
|
43
|
+
'qt',
|
|
44
|
+
'mts',
|
|
45
|
+
'm2ts',
|
|
46
|
+
'ts',
|
|
47
|
+
'wmv',
|
|
48
|
+
'yuv',
|
|
49
|
+
'rm',
|
|
50
|
+
'rmvb',
|
|
51
|
+
'viv',
|
|
52
|
+
'asf',
|
|
53
|
+
'amv',
|
|
54
|
+
'm4p',
|
|
55
|
+
'mpeg',
|
|
56
|
+
'mpe',
|
|
57
|
+
'm2v',
|
|
58
|
+
'm4v',
|
|
59
|
+
'svi',
|
|
60
|
+
'3gp',
|
|
61
|
+
'3g2',
|
|
62
|
+
'mxf',
|
|
63
|
+
'roq',
|
|
64
|
+
'nsv',
|
|
65
|
+
'f4v',
|
|
66
|
+
'f4p',
|
|
67
|
+
'f4a',
|
|
68
|
+
'f4b',
|
|
69
|
+
];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { traverse } from './traverse';
|
|
2
|
+
|
|
3
|
+
const isLocalizedField = (value: any) => {
|
|
4
|
+
return value && typeof value === 'object' && value['@type'] === '@builder.io/core:LocalizedValue';
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const containsLocalizedValues = (data: Record<string, any>) => {
|
|
8
|
+
if (!data || !Object.getOwnPropertyNames(data).length) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
let hasLocalizedValues = false;
|
|
12
|
+
traverse(data, value => {
|
|
13
|
+
if (isLocalizedField(value)) {
|
|
14
|
+
hasLocalizedValues = true;
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
return hasLocalizedValues;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const extractLocalizedValues = (data: Record<string, any>, locale: string) => {
|
|
22
|
+
if (!data || !Object.getOwnPropertyNames(data).length) {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
traverse(data, (value, update) => {
|
|
27
|
+
if (isLocalizedField(value)) {
|
|
28
|
+
update(value[locale] ?? undefined);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
return data;
|
|
33
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
type TraverseCallback = (value: any, update: (newValue: any) => void) => void;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Recursively traverses an object or array, invoking a callback on each value.
|
|
5
|
+
*
|
|
6
|
+
* @param {any} obj - The object or array to traverse. Can also handle primitives, null, or undefined.
|
|
7
|
+
* @param {TraverseCallback} callback - The function to invoke on each value. Receives the current value
|
|
8
|
+
* and an `update` function to modify the value in its parent container.
|
|
9
|
+
* @param {any} [parent=null] - The parent object or array of the current value. Used internally.
|
|
10
|
+
* @param {any} [key=null] - The key or index of the current value in its parent. Used internally.
|
|
11
|
+
* @param {WeakSet} [visited=new WeakSet()] - Tracks visited objects to handle circular references. Used internally.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // Example: Doubling all numbers in an object
|
|
15
|
+
* const obj = { a: 1, b: [2, 3, { c: 4 }] };
|
|
16
|
+
* traverse(obj, (value, update) => {
|
|
17
|
+
* if (typeof value === 'number') {
|
|
18
|
+
* update(value * 2);
|
|
19
|
+
* }
|
|
20
|
+
* });
|
|
21
|
+
* console.log(obj); // { a: 2, b: [4, 6, { c: 8 }] }
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // Example: Handling circular references
|
|
25
|
+
* const obj = { a: 1 };
|
|
26
|
+
* obj.self = obj;
|
|
27
|
+
* traverse(obj, (value, update) => {
|
|
28
|
+
* if (typeof value === 'number') {
|
|
29
|
+
* update(value * 2);
|
|
30
|
+
* }
|
|
31
|
+
* });
|
|
32
|
+
* console.log(obj.a); // 2
|
|
33
|
+
*/
|
|
34
|
+
export function traverse(
|
|
35
|
+
obj: any,
|
|
36
|
+
callback: TraverseCallback,
|
|
37
|
+
parent: any = null,
|
|
38
|
+
key: any = null,
|
|
39
|
+
visited = new WeakSet()
|
|
40
|
+
): void {
|
|
41
|
+
if (obj == null || typeof obj !== 'object') {
|
|
42
|
+
callback(obj, (newValue: any) => {
|
|
43
|
+
if (parent !== null && key !== null) {
|
|
44
|
+
parent[key] = newValue;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (visited.has(obj)) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
visited.add(obj);
|
|
54
|
+
|
|
55
|
+
if (Array.isArray(obj)) {
|
|
56
|
+
obj.forEach((item, index) => {
|
|
57
|
+
const update = (newValue: any) => {
|
|
58
|
+
obj[index] = newValue;
|
|
59
|
+
};
|
|
60
|
+
callback(item, update);
|
|
61
|
+
traverse(item, callback, obj, index, visited);
|
|
62
|
+
});
|
|
63
|
+
} else {
|
|
64
|
+
Object.entries(obj).forEach(([key, value]) => {
|
|
65
|
+
const update = (newValue: any) => {
|
|
66
|
+
obj[key] = newValue;
|
|
67
|
+
};
|
|
68
|
+
callback(value, update);
|
|
69
|
+
traverse(value, callback, obj, key, visited);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|