@builder.io/react 2.0.3 → 2.0.4-10

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 (43) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/builder-react-lite.cjs.js +1 -1
  3. package/dist/builder-react-lite.cjs.js.map +1 -1
  4. package/dist/builder-react-lite.esm.js +1 -1
  5. package/dist/builder-react-lite.esm.js.map +1 -1
  6. package/dist/builder-react.browser.js +1 -1
  7. package/dist/builder-react.browser.js.map +1 -1
  8. package/dist/builder-react.cjs.js +1 -1
  9. package/dist/builder-react.cjs.js.map +1 -1
  10. package/dist/builder-react.es5.js +1 -1
  11. package/dist/builder-react.es5.js.map +1 -1
  12. package/dist/builder-react.unpkg.js +1 -1
  13. package/dist/builder-react.unpkg.js.map +1 -1
  14. package/dist/lib/package.json +4 -2
  15. package/dist/lib/src/blocks/Section.js +2 -0
  16. package/dist/lib/src/blocks/Section.js.map +1 -1
  17. package/dist/lib/src/blocks/Symbol.js +2 -2
  18. package/dist/lib/src/blocks/Symbol.js.map +1 -1
  19. package/dist/lib/src/components/builder-block.component.js +17 -11
  20. package/dist/lib/src/components/builder-block.component.js.map +1 -1
  21. package/dist/lib/src/components/builder-blocks.component.js.map +1 -1
  22. package/dist/lib/src/components/builder-component.component.js +30 -73
  23. package/dist/lib/src/components/builder-component.component.js.map +1 -1
  24. package/dist/lib/src/components/builder-content.component.js +5 -4
  25. package/dist/lib/src/components/builder-content.component.js.map +1 -1
  26. package/dist/lib/src/functions/apply-patch-with-mutation.js +1 -1
  27. package/dist/lib/src/functions/apply-patch-with-mutation.js.map +1 -1
  28. package/dist/lib/src/functions/apply-patch-with-mutation.test.js +54 -0
  29. package/dist/lib/src/functions/apply-patch-with-mutation.test.js.map +1 -0
  30. package/dist/lib/src/scripts/init-editing.js +1 -1
  31. package/dist/types/src/components/builder-component.component.d.ts +6 -0
  32. package/dist/types/src/functions/apply-patch-with-mutation.d.ts +2 -2
  33. package/dist/types/src/functions/apply-patch-with-mutation.test.d.ts +1 -0
  34. package/package.json +4 -2
  35. package/src/blocks/Section.tsx +16 -11
  36. package/src/blocks/Symbol.tsx +1 -0
  37. package/src/components/builder-block.component.tsx +26 -14
  38. package/src/components/builder-blocks.component.tsx +10 -8
  39. package/src/components/builder-component.component.tsx +35 -73
  40. package/src/components/builder-content.component.tsx +4 -4
  41. package/src/functions/apply-patch-with-mutation.test.ts +55 -0
  42. package/src/functions/apply-patch-with-mutation.ts +5 -5
  43. package/src/scripts/init-editing.ts +1 -1
@@ -98,31 +98,6 @@ const sizeMap = {
98
98
  mobile: 'small',
99
99
  };
100
100
 
101
- function decorator(fn: Function) {
102
- return function argReceiver(...fnArgs: any[]) {
103
- // Check if the decorator is being called without arguments (ex `@foo methodName() {}`)
104
- if (fnArgs.length === 3) {
105
- const [target, key, descriptor] = fnArgs;
106
- if (descriptor && (descriptor.value || descriptor.get)) {
107
- fnArgs = [];
108
- return descriptorChecker(target, key, descriptor);
109
- }
110
- }
111
-
112
- return descriptorChecker;
113
-
114
- // descriptorChecker determines whether a method or getter is being decorated
115
- // and replaces the appropriate key with the decorated function.
116
- function descriptorChecker(target: any, key: any, descriptor: any) {
117
- const descriptorKey = descriptor.value ? 'value' : 'get';
118
- return {
119
- ...descriptor,
120
- [descriptorKey]: fn(descriptor[descriptorKey], ...fnArgs),
121
- };
122
- }
123
- };
124
- }
125
-
126
101
  const fetchCache: { [key: string]: any } = {};
127
102
 
128
103
  export interface BuilderComponentProps {
@@ -301,6 +276,11 @@ export interface BuilderComponentProps {
301
276
  * navigation to other pages unintended
302
277
  */
303
278
  stopClickPropagationWhenEditing?: boolean;
279
+
280
+ /**
281
+ * Locale code, should match one of the locales in your spaces locale, wll auto resolve the localized inputs to the localized value
282
+ */
283
+ locale?: string;
304
284
  }
305
285
 
306
286
  export interface BuilderComponentState {
@@ -865,7 +845,7 @@ export class BuilderComponent extends React.Component<
865
845
  get data() {
866
846
  const data = {
867
847
  ...(this.inlinedContent && this.inlinedContent.data?.state),
868
- ...this.props.data,
848
+ ...this.externalState,
869
849
  ...this.state.state,
870
850
  };
871
851
  Object.assign(this.rootState, data);
@@ -876,7 +856,7 @@ export class BuilderComponent extends React.Component<
876
856
  // TODO: shallow diff
877
857
  if (this.props.data && prevProps.data !== this.props.data) {
878
858
  this.state.update((state: any) => {
879
- Object.assign(state, this.props.data);
859
+ Object.assign(state, this.externalState);
880
860
  });
881
861
  }
882
862
 
@@ -916,6 +896,13 @@ export class BuilderComponent extends React.Component<
916
896
  return content;
917
897
  }
918
898
 
899
+ get externalState() {
900
+ return {
901
+ ...this.props.data,
902
+ ...(this.props.locale ? { locale: this.props.locale } : {}),
903
+ };
904
+ }
905
+
919
906
  get useContent() {
920
907
  return this.content || this.state.context.builderContent;
921
908
  }
@@ -924,7 +911,10 @@ export class BuilderComponent extends React.Component<
924
911
  const content = this.content;
925
912
 
926
913
  const dataString =
927
- Builder.isBrowser && this.props.data && size(this.props.data) && hash(this.props.data);
914
+ Builder.isBrowser &&
915
+ this.externalState &&
916
+ size(this.externalState) &&
917
+ hash(this.externalState);
928
918
  let key = Builder.isEditing ? this.name : this.props.entry;
929
919
  if (key && !Builder.isEditing && dataString && dataString.length < 300) {
930
920
  key += ':' + dataString;
@@ -995,6 +985,7 @@ export class BuilderComponent extends React.Component<
995
985
  !this.isPreviewing && { initialContent: [] }),
996
986
  ...(this.props.url && { url: this.props.url }),
997
987
  ...this.props.options,
988
+ ...(this.props.locale ? { locale: this.props.locale } : {}),
998
989
  ...(this.options.codegen && {
999
990
  format: 'react',
1000
991
  }),
@@ -1264,7 +1255,6 @@ export class BuilderComponent extends React.Component<
1264
1255
  this.notifyStateChange();
1265
1256
  }
1266
1257
 
1267
- // Unsubscribe all? TODO: maybe don't continuous fire when editing.....
1268
1258
  if (this.props.contentLoaded) {
1269
1259
  this.props.contentLoaded(data, content);
1270
1260
  }
@@ -1274,12 +1264,6 @@ export class BuilderComponent extends React.Component<
1274
1264
  data.state = {};
1275
1265
  }
1276
1266
 
1277
- // Maybe...
1278
- // if (data.context) {
1279
- // Object.assign(this.state.context, data.context)
1280
- // }
1281
- // TODO: may not want this... or make sure anything overriden
1282
- // explitily sets to null
1283
1267
  data.inputs.forEach((input: any) => {
1284
1268
  if (input) {
1285
1269
  if (
@@ -1303,7 +1287,7 @@ export class BuilderComponent extends React.Component<
1303
1287
  deviceSize: this.deviceSizeState,
1304
1288
  device: this.device,
1305
1289
  ...data.state,
1306
- ...this.props.data,
1290
+ ...this.externalState,
1307
1291
  }),
1308
1292
  };
1309
1293
  if (this.mounted) {
@@ -1380,8 +1364,6 @@ export class BuilderComponent extends React.Component<
1380
1364
  for (const key in data.httpRequests) {
1381
1365
  const url: string | undefined = data.httpRequests[key];
1382
1366
  if (url && (!this.data[key] || Builder.isEditing)) {
1383
- // TODO: if Builder.isEditing and url patches https://builder.io/api/v2/content/{editingModel}
1384
- // Then use this.builder.get().subscribe(...)
1385
1367
  if (Builder.isBrowser) {
1386
1368
  const finalUrl = this.evalExpression(url);
1387
1369
  if (Builder.isEditing && this.lastHttpRequests[key] === finalUrl) {
@@ -1391,47 +1373,27 @@ export class BuilderComponent extends React.Component<
1391
1373
  const builderModelRe = /builder\.io\/api\/v2\/([^\/\?]+)/i;
1392
1374
  const builderModelMatch = url.match(builderModelRe);
1393
1375
  const model = builderModelMatch && builderModelMatch[1];
1394
- if (false && Builder.isEditing && model && this.builder.editingModel === model) {
1395
- this.handleRequest(key, finalUrl);
1396
- // TODO: fix this
1397
- // this.subscriptions.add(
1398
- // this.builder.get(model).subscribe(data => {
1399
- // this.state.update((state: any) => {
1400
- // state[key] = data
1401
- // })
1402
- // })
1403
- // )
1404
- } else {
1405
- this.handleRequest(key, finalUrl);
1406
- const currentSubscription = this.httpSubscriptionPerKey[key];
1407
- if (currentSubscription) {
1408
- currentSubscription.unsubscribe();
1409
- }
1410
-
1411
- // TODO: fix this
1412
- const newSubscription = (this.httpSubscriptionPerKey[key] =
1413
- this.onStateChange.subscribe(() => {
1414
- const newUrl = this.evalExpression(url);
1415
- if (newUrl !== finalUrl) {
1416
- this.handleRequest(key, newUrl);
1417
- this.lastHttpRequests[key] = newUrl;
1418
- }
1419
- }));
1420
- this.subscriptions.add(newSubscription);
1376
+ this.handleRequest(key, finalUrl);
1377
+ const currentSubscription = this.httpSubscriptionPerKey[key];
1378
+ if (currentSubscription) {
1379
+ currentSubscription.unsubscribe();
1421
1380
  }
1381
+
1382
+ // TODO: fix this
1383
+ const newSubscription = (this.httpSubscriptionPerKey[key] =
1384
+ this.onStateChange.subscribe(() => {
1385
+ const newUrl = this.evalExpression(url);
1386
+ if (newUrl !== finalUrl) {
1387
+ this.handleRequest(key, newUrl);
1388
+ this.lastHttpRequests[key] = newUrl;
1389
+ }
1390
+ }));
1391
+ this.subscriptions.add(newSubscription);
1422
1392
  } else {
1423
1393
  this.handleRequest(key, this.evalExpression(url));
1424
1394
  }
1425
1395
  }
1426
1396
  }
1427
-
1428
- // @DEPRECATED
1429
- // for (const key in data.builderData) {
1430
- // const url = data.builderData[key]
1431
- // if (url && !this.data[key]) {
1432
- // this.handleBuilderRequest(key, this.evalExpression(url))
1433
- // }
1434
- // }
1435
1397
  }
1436
1398
  }
1437
1399
  };
@@ -140,17 +140,17 @@ export class BuilderContent<ContentType extends object = any> extends React.Comp
140
140
  if (location.href.includes('builder.debug=true')) {
141
141
  eval('debugger');
142
142
  }
143
+ let newData = this.state.data as any;
143
144
  for (const patch of patches) {
144
- applyPatchWithMinimalMutationChain(this.state.data, patch);
145
+ newData = applyPatchWithMinimalMutationChain(newData, patch, false);
145
146
  }
146
147
  this.setState({
147
148
  updates: this.state.updates + 1,
148
- data: this.state.data ? { ...this.state.data } : this.state.data,
149
+ data: newData,
149
150
  });
150
151
  if (this.props.contentLoaded) {
151
- this.props.contentLoaded(this.state.data?.data, this.state.data);
152
+ this.props.contentLoaded(newData.data, newData);
152
153
  }
153
-
154
154
  break;
155
155
  }
156
156
  }
@@ -0,0 +1,55 @@
1
+ import { applyPatchWithMinimalMutationChain } from './apply-patch-with-mutation';
2
+
3
+ describe('applyPatchWithMinimalMutationChain', () => {
4
+ test('Basic shallow update', () => {
5
+ const obj = {
6
+ foo: 'bar',
7
+ };
8
+ const patch = {
9
+ op: 'replace',
10
+ path: '/foo',
11
+ value: '60px',
12
+ } as const;
13
+ const applied = applyPatchWithMinimalMutationChain(obj, patch);
14
+ expect(applied.foo).toBe('60px');
15
+ expect(applied).not.toBe(obj);
16
+ });
17
+
18
+ test('Deep object updates', () => {
19
+ const obj = {
20
+ foo: {
21
+ bar: true,
22
+ },
23
+ baz: {},
24
+ };
25
+ const patch = {
26
+ op: 'replace',
27
+ path: '/foo/bar',
28
+ value: '60px',
29
+ } as const;
30
+ const applied = applyPatchWithMinimalMutationChain(obj, patch);
31
+ expect(applied.foo.bar).toBe('60px');
32
+ expect(applied).not.toBe(obj);
33
+ expect(applied.foo).not.toBe(obj.foo);
34
+ expect(applied.baz).toBe(obj.baz);
35
+ });
36
+
37
+ test('Deep array updates', () => {
38
+ const obj = {
39
+ foo: [{ bar: true }],
40
+ baz: {},
41
+ };
42
+ const patch = {
43
+ op: 'replace',
44
+ path: '/foo/0/bar',
45
+ value: '60px',
46
+ } as const;
47
+
48
+ const applied = applyPatchWithMinimalMutationChain(obj, patch);
49
+ expect(applied.foo[0].bar).toBe('60px');
50
+ expect(applied).not.toBe(obj);
51
+ expect(applied.foo).not.toBe(obj.foo);
52
+ expect(applied.foo[0]).not.toBe(obj.foo[0]);
53
+ expect(applied.baz).toBe(obj.baz);
54
+ });
55
+ });
@@ -1,8 +1,8 @@
1
- export const applyPatchWithMinimalMutationChain = (
2
- obj: any,
1
+ export const applyPatchWithMinimalMutationChain = <T extends object>(
2
+ obj: T,
3
3
  patch: { path: string; op: 'add' | 'remove' | 'replace'; value: any },
4
- preserveRoot = true
5
- ) => {
4
+ preserveRoot = false
5
+ ): T => {
6
6
  if (Object(obj) !== obj) {
7
7
  return obj;
8
8
  }
@@ -13,7 +13,7 @@ export const applyPatchWithMinimalMutationChain = (
13
13
  }
14
14
 
15
15
  const newObj = preserveRoot ? obj : { ...obj };
16
- let objPart = newObj;
16
+ let objPart = newObj as any;
17
17
  for (let i = 0; i < pathArr.length; i++) {
18
18
  const isLast = i === pathArr.length - 1;
19
19
  const property = pathArr[i];
@@ -6,7 +6,7 @@ if (typeof window !== 'undefined') {
6
6
  type: 'builder.isReactSdk',
7
7
  data: {
8
8
  value: true,
9
- supportsPatchUpdates: 'v3',
9
+ supportsPatchUpdates: 'v4',
10
10
  priorVersion: version,
11
11
  },
12
12
  },