@movable/studio-framework 3.0.0-canary.0 → 3.0.0-esmodules.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/dist/index.es.js +522 -125
- package/dist/index.es.js.map +7 -0
- package/dist/index.js +563 -161
- package/package.json +29 -33
package/dist/index.es.js
CHANGED
|
@@ -44,13 +44,50 @@ function _extends() {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
const {
|
|
47
|
-
entries
|
|
47
|
+
entries: entries$2
|
|
48
48
|
} = Object;
|
|
49
|
-
const STYLE_WHITELIST =
|
|
49
|
+
const STYLE_WHITELIST = {
|
|
50
|
+
top: true,
|
|
51
|
+
left: true,
|
|
52
|
+
color: true,
|
|
53
|
+
width: true,
|
|
54
|
+
border: true,
|
|
55
|
+
borderRadius: true,
|
|
56
|
+
borderColor: true,
|
|
57
|
+
borderStyle: true,
|
|
58
|
+
borderWidth: true,
|
|
59
|
+
boxSizing: true,
|
|
60
|
+
boxShadow: true,
|
|
61
|
+
height: true,
|
|
62
|
+
marginTop: true,
|
|
63
|
+
marginLeft: true,
|
|
64
|
+
marginBottom: true,
|
|
65
|
+
marginRight: true,
|
|
66
|
+
zIndex: true,
|
|
67
|
+
fontSize: true,
|
|
68
|
+
position: true,
|
|
69
|
+
textAlign: true,
|
|
70
|
+
transform: true,
|
|
71
|
+
textShadow: true,
|
|
72
|
+
lineHeight: true,
|
|
73
|
+
fontFamily: true,
|
|
74
|
+
fontWeight: true,
|
|
75
|
+
textTransform: true,
|
|
76
|
+
letterSpacing: true,
|
|
77
|
+
backgroundColor: true,
|
|
78
|
+
backgroundImage: true,
|
|
79
|
+
transformOrigin: true,
|
|
80
|
+
opacity: true,
|
|
81
|
+
overflow: true,
|
|
82
|
+
display: true,
|
|
83
|
+
flexDirection: true,
|
|
84
|
+
justifyContent: true,
|
|
85
|
+
whiteSpace: true
|
|
86
|
+
};
|
|
50
87
|
const PROPERTY_TRANSFORMS = {
|
|
51
88
|
transform: value => `rotate(${value}deg)`
|
|
52
89
|
};
|
|
53
|
-
const TRANSFORMS_MAP = new Map(entries(PROPERTY_TRANSFORMS));
|
|
90
|
+
const TRANSFORMS_MAP = new Map(entries$2(PROPERTY_TRANSFORMS));
|
|
54
91
|
|
|
55
92
|
function transformStyle(key, value) {
|
|
56
93
|
const transform = TRANSFORMS_MAP.get(key);
|
|
@@ -58,9 +95,13 @@ function transformStyle(key, value) {
|
|
|
58
95
|
}
|
|
59
96
|
|
|
60
97
|
function styleFromAttributes(tag) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
98
|
+
const result = {};
|
|
99
|
+
|
|
100
|
+
for (const key of Object.keys(tag)) {
|
|
101
|
+
if (STYLE_WHITELIST[key]) result[key] = transformStyle(key, tag[key]);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return result;
|
|
64
105
|
}
|
|
65
106
|
|
|
66
107
|
function normalizeRichTextStyles(attributes = {}) {
|
|
@@ -121,7 +162,7 @@ class StyledElement extends React.Component {
|
|
|
121
162
|
tag,
|
|
122
163
|
registryResolver
|
|
123
164
|
} = this.props;
|
|
124
|
-
const elementModifierFunctions = resolveElementModifiers(
|
|
165
|
+
const elementModifierFunctions = resolveElementModifiers(tag?.appliedElementModifiers || [], registryResolver);
|
|
125
166
|
runModifiers(domNode, elementModifierFunctions);
|
|
126
167
|
}
|
|
127
168
|
}
|
|
@@ -364,6 +405,13 @@ function StudioErrorWrapper(error, message) {
|
|
|
364
405
|
|
|
365
406
|
return error.clone(wrappedMessage);
|
|
366
407
|
}
|
|
408
|
+
class StudioError extends BaseStudioError {
|
|
409
|
+
constructor(dynamicProperty, message) {
|
|
410
|
+
super(message);
|
|
411
|
+
this.setSourceDynamicProperty(dynamicProperty);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
}
|
|
367
415
|
|
|
368
416
|
function getStateTuple(prop, resolver) {
|
|
369
417
|
if (!prop) {
|
|
@@ -427,6 +475,7 @@ class TagComponent extends React.Component {
|
|
|
427
475
|
getPropertyWithFallback(prop, fallback) {
|
|
428
476
|
const {
|
|
429
477
|
tag,
|
|
478
|
+
canvas,
|
|
430
479
|
propertyResolver
|
|
431
480
|
} = this.props;
|
|
432
481
|
const [result, error] = getStateTuple(prop, propertyResolver);
|
|
@@ -436,7 +485,7 @@ class TagComponent extends React.Component {
|
|
|
436
485
|
|
|
437
486
|
if (propertyFallback) {
|
|
438
487
|
const warning = error ? StudioErrorWrapper(error, 'Fallback Warning') : new BaseStudioError('Fallback Warning');
|
|
439
|
-
const consoleMessage = warning.setErrorType('FallbackWarning').setTag(tag).setSourceDynamicProperty(prop).setEntryDynamicProperty(prop);
|
|
488
|
+
const consoleMessage = warning.setErrorType('FallbackWarning').setTag(tag).setCanvas(canvas).setSourceType('tag').setSourceDynamicProperty(prop).setEntryDynamicProperty(prop);
|
|
440
489
|
console.warn(consoleMessage);
|
|
441
490
|
return propertyFallback;
|
|
442
491
|
}
|
|
@@ -444,10 +493,10 @@ class TagComponent extends React.Component {
|
|
|
444
493
|
if (passedFallback) return fallback;
|
|
445
494
|
|
|
446
495
|
if (error) {
|
|
447
|
-
throw StudioErrorWrapper(error).setTag(tag);
|
|
496
|
+
throw StudioErrorWrapper(error).setTag(tag).setCanvas(canvas).setSourceType('tag');
|
|
448
497
|
}
|
|
449
498
|
|
|
450
|
-
throw new BaseStudioError('Missing Data').setErrorType('MissingData').setTag(tag).setSourceDynamicProperty(prop).setEntryDynamicProperty(prop);
|
|
499
|
+
throw new BaseStudioError('Missing Data').setErrorType('MissingData').setTag(tag).setCanvas(canvas).setSourceType('tag').setSourceDynamicProperty(prop).setEntryDynamicProperty(prop);
|
|
451
500
|
}
|
|
452
501
|
|
|
453
502
|
constructor(props) {
|
|
@@ -495,7 +544,8 @@ class Tags extends React.Component {
|
|
|
495
544
|
registryResolver,
|
|
496
545
|
propertyResolver,
|
|
497
546
|
onPendingPromise,
|
|
498
|
-
tags
|
|
547
|
+
tags,
|
|
548
|
+
canvas
|
|
499
549
|
} = this.props;
|
|
500
550
|
return tags.map((tag, index) => {
|
|
501
551
|
const {
|
|
@@ -507,11 +557,13 @@ class Tags extends React.Component {
|
|
|
507
557
|
registryResolver: registryResolver
|
|
508
558
|
}, subtags ? /*#__PURE__*/React.createElement(Tags, {
|
|
509
559
|
tags: subtags,
|
|
560
|
+
canvas: canvas,
|
|
510
561
|
registryResolver: registryResolver,
|
|
511
562
|
propertyResolver: propertyResolver,
|
|
512
563
|
onPendingPromise: onPendingPromise
|
|
513
564
|
}) : /*#__PURE__*/React.createElement(TagComponent, {
|
|
514
565
|
tag: tag,
|
|
566
|
+
canvas: canvas,
|
|
515
567
|
registryResolver: registryResolver,
|
|
516
568
|
propertyResolver: propertyResolver,
|
|
517
569
|
onPendingPromise: onPendingPromise
|
|
@@ -530,7 +582,7 @@ class SizeContainer extends React.Component {
|
|
|
530
582
|
canvas,
|
|
531
583
|
registryResolver
|
|
532
584
|
} = this.props;
|
|
533
|
-
const elementModifierFunctions = resolveElementModifiers(
|
|
585
|
+
const elementModifierFunctions = resolveElementModifiers(canvas?.appliedElementModifiers || [], registryResolver);
|
|
534
586
|
runModifiers(domNode, elementModifierFunctions);
|
|
535
587
|
}
|
|
536
588
|
}
|
|
@@ -646,7 +698,6 @@ function contextAccessor(context, cb) {
|
|
|
646
698
|
let _Symbol$iterator;
|
|
647
699
|
|
|
648
700
|
const ERROR_KEY = Symbol('error');
|
|
649
|
-
const TEMP_STORAGE = Symbol('temporary-key');
|
|
650
701
|
|
|
651
702
|
function isError(t) {
|
|
652
703
|
return t && typeof t === 'object' && ERROR_KEY in t;
|
|
@@ -666,6 +717,8 @@ class CacheMap {
|
|
|
666
717
|
_defineProperty(this, "acceptingKeys", true);
|
|
667
718
|
|
|
668
719
|
_defineProperty(this, "tempContext", void 0);
|
|
720
|
+
|
|
721
|
+
_defineProperty(this, "tempStorageKey", context => JSON.stringify(context));
|
|
669
722
|
}
|
|
670
723
|
|
|
671
724
|
get(context) {
|
|
@@ -703,11 +756,12 @@ class CacheMap {
|
|
|
703
756
|
|
|
704
757
|
freezeContext() {
|
|
705
758
|
this.acceptingKeys = false;
|
|
759
|
+
const temp = this.tempStorageKey(this.tempContext);
|
|
706
760
|
|
|
707
|
-
if (this.cache.has(
|
|
708
|
-
const value = this.cache.get(
|
|
761
|
+
if (this.cache.has(temp)) {
|
|
762
|
+
const value = this.cache.get(temp);
|
|
709
763
|
const context = this.tempContext;
|
|
710
|
-
this.cache.delete(
|
|
764
|
+
this.cache.delete(temp);
|
|
711
765
|
this.cache.set(this.cacheKeyFor(context), value);
|
|
712
766
|
}
|
|
713
767
|
}
|
|
@@ -725,7 +779,7 @@ class CacheMap {
|
|
|
725
779
|
cacheKeyFor(context) {
|
|
726
780
|
if (this.acceptingKeys) {
|
|
727
781
|
this.tempContext = context;
|
|
728
|
-
return
|
|
782
|
+
return this.tempStorageKey(context);
|
|
729
783
|
}
|
|
730
784
|
|
|
731
785
|
if (this.keyCache.has(context)) {
|
|
@@ -784,6 +838,7 @@ class ComputeThrottler {
|
|
|
784
838
|
result = compute();
|
|
785
839
|
} catch (e) {
|
|
786
840
|
this.isPending = false;
|
|
841
|
+
this.tryNextInQueue();
|
|
787
842
|
throw e;
|
|
788
843
|
}
|
|
789
844
|
|
|
@@ -874,6 +929,31 @@ function parseGetPropertyArgs(args) {
|
|
|
874
929
|
return [false, '', arg3];
|
|
875
930
|
}
|
|
876
931
|
}
|
|
932
|
+
function parseGetPropertyProxyArgs(args) {
|
|
933
|
+
let callback = null;
|
|
934
|
+
|
|
935
|
+
if (typeof args[args.length - 1] === 'function') {
|
|
936
|
+
callback = args.pop();
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
if (!callback) {
|
|
940
|
+
callback = (_, error) => {
|
|
941
|
+
if (error) {
|
|
942
|
+
throw error;
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
const [arg1, arg2, arg3] = args;
|
|
948
|
+
|
|
949
|
+
if (typeof arg2 === 'string' && typeof arg3 !== 'function') {
|
|
950
|
+
return [arg1, arg2, arg3, callback];
|
|
951
|
+
} else if (typeof arg1 === 'string' && typeof arg2 !== 'function' && typeof arg2 !== 'string') {
|
|
952
|
+
return [false, arg1, arg2, callback];
|
|
953
|
+
} else if (typeof arg3 !== 'function') {
|
|
954
|
+
return [false, '', arg3, callback];
|
|
955
|
+
}
|
|
956
|
+
}
|
|
877
957
|
function parseSetPropertyArgs(args) {
|
|
878
958
|
if (args.length === 2) {
|
|
879
959
|
const [arg1, arg2] = args;
|
|
@@ -883,18 +963,42 @@ function parseSetPropertyArgs(args) {
|
|
|
883
963
|
}
|
|
884
964
|
}
|
|
885
965
|
|
|
886
|
-
|
|
966
|
+
/** This implementation is adapted from uuidjs rather than requiring the full library
|
|
967
|
+
* see: https://github.com/movableink/studio-framework/pull/762#discussion_r555175040
|
|
968
|
+
*/
|
|
969
|
+
const byteToHex = [];
|
|
970
|
+
|
|
971
|
+
for (let i = 0; i < 256; ++i) {
|
|
972
|
+
byteToHex.push((i + 0x100).toString(16).substr(1));
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
function generateV4Uuid() {
|
|
976
|
+
// generate cryptographically strong random numbers
|
|
977
|
+
// see: github.com/uuidjs/uuid/blob/master/src/rng-browser.js
|
|
978
|
+
const unsigned8BitArray = new Uint8Array(16);
|
|
979
|
+
const getRandomValues = crypto.getRandomValues.bind(crypto);
|
|
980
|
+
const randomValues = getRandomValues(unsigned8BitArray); // per 4.4, set bits for version and `clock_seq_hi_and_reserved`
|
|
981
|
+
// see: github.com/uuidjs/uuid/blob/master/src/v4.js
|
|
887
982
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
DebugType["resolve"] = "resolve";
|
|
892
|
-
DebugType["await"] = "await";
|
|
893
|
-
DebugType["error"] = "error";
|
|
894
|
-
DebugType["override"] = "override";
|
|
895
|
-
})(DebugType || (DebugType = {}));
|
|
983
|
+
randomValues[6] = randomValues[6] & 0x0f | 0x40;
|
|
984
|
+
randomValues[8] = randomValues[8] & 0x3f | 0x80; // strigify v4 format
|
|
985
|
+
// see: github.com/uuidjs/uuid/blob/master/src/stringify.js
|
|
896
986
|
|
|
897
|
-
|
|
987
|
+
return (byteToHex[randomValues[0]] + byteToHex[randomValues[1]] + byteToHex[randomValues[2]] + byteToHex[randomValues[3]] + '-' + byteToHex[randomValues[4]] + byteToHex[randomValues[5]] + '-' + byteToHex[randomValues[6]] + byteToHex[randomValues[7]] + '-' + byteToHex[randomValues[8]] + byteToHex[randomValues[9]] + '-' + byteToHex[randomValues[10]] + byteToHex[randomValues[11]] + byteToHex[randomValues[12]] + byteToHex[randomValues[13]] + byteToHex[randomValues[14]] + byteToHex[randomValues[15]]).toLowerCase();
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
let EventType;
|
|
991
|
+
|
|
992
|
+
(function (EventType) {
|
|
993
|
+
EventType["cacheRead"] = "cache-read";
|
|
994
|
+
EventType["propertyRequest"] = "property-request";
|
|
995
|
+
EventType["resolve"] = "resolve";
|
|
996
|
+
EventType["await"] = "await";
|
|
997
|
+
EventType["error"] = "error";
|
|
998
|
+
EventType["override"] = "override";
|
|
999
|
+
})(EventType || (EventType = {}));
|
|
1000
|
+
|
|
1001
|
+
class InertEvent {
|
|
898
1002
|
makeChildEvent() {
|
|
899
1003
|
return this;
|
|
900
1004
|
} // eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
@@ -907,8 +1011,12 @@ class InertDebugEvent {
|
|
|
907
1011
|
|
|
908
1012
|
}
|
|
909
1013
|
|
|
910
|
-
class
|
|
1014
|
+
class ActiveEvent {
|
|
911
1015
|
constructor(type, dynamicProperty) {
|
|
1016
|
+
_defineProperty(this, "id", void 0);
|
|
1017
|
+
|
|
1018
|
+
_defineProperty(this, "createdAt", void 0);
|
|
1019
|
+
|
|
912
1020
|
_defineProperty(this, "type", void 0);
|
|
913
1021
|
|
|
914
1022
|
_defineProperty(this, "dynamicProperty", void 0);
|
|
@@ -921,10 +1029,12 @@ class ActiveDebugEvent {
|
|
|
921
1029
|
|
|
922
1030
|
this.type = type;
|
|
923
1031
|
this.dynamicProperty = dynamicProperty;
|
|
1032
|
+
this.id = generateV4Uuid();
|
|
1033
|
+
this.createdAt = Date.now();
|
|
924
1034
|
}
|
|
925
1035
|
|
|
926
1036
|
makeChildEvent(type, prop) {
|
|
927
|
-
const event = new
|
|
1037
|
+
const event = new ActiveEvent(type, prop || this.dynamicProperty);
|
|
928
1038
|
this.childEvents.push(event);
|
|
929
1039
|
return event;
|
|
930
1040
|
}
|
|
@@ -939,10 +1049,10 @@ class ActiveDebugEvent {
|
|
|
939
1049
|
|
|
940
1050
|
}
|
|
941
1051
|
function createEvent(type, prop) {
|
|
942
|
-
return new
|
|
1052
|
+
return new ActiveEvent(type, prop);
|
|
943
1053
|
}
|
|
944
1054
|
function createInertEvent() {
|
|
945
|
-
return new
|
|
1055
|
+
return new InertEvent();
|
|
946
1056
|
}
|
|
947
1057
|
|
|
948
1058
|
function deprecateGetContext(key) {
|
|
@@ -1004,6 +1114,10 @@ class Property {
|
|
|
1004
1114
|
return this.overrideFn;
|
|
1005
1115
|
}
|
|
1006
1116
|
|
|
1117
|
+
get dependencies() {
|
|
1118
|
+
return this.dependentProperties;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1007
1121
|
getCacheFor(context) {
|
|
1008
1122
|
if (this.memoizeCache) {
|
|
1009
1123
|
return this.memoizeCache.get(context);
|
|
@@ -1072,8 +1186,9 @@ class Property {
|
|
|
1072
1186
|
|
|
1073
1187
|
getPropertyProxy(context, requestEvent) {
|
|
1074
1188
|
return (...args) => {
|
|
1075
|
-
const [grouping, key, extraContext = {}] =
|
|
1076
|
-
const
|
|
1189
|
+
const [grouping, key, extraContext = {}, callback] = parseGetPropertyProxyArgs(args);
|
|
1190
|
+
const propertyGroupKey = grouping || this.grouping;
|
|
1191
|
+
const property = this.computed.getPropertyInstance(propertyGroupKey, key);
|
|
1077
1192
|
|
|
1078
1193
|
if (!property) {
|
|
1079
1194
|
return null;
|
|
@@ -1084,21 +1199,89 @@ class Property {
|
|
|
1084
1199
|
...extraContext
|
|
1085
1200
|
};
|
|
1086
1201
|
const prop = {
|
|
1087
|
-
propertyGroupKey:
|
|
1202
|
+
propertyGroupKey: propertyGroupKey,
|
|
1088
1203
|
propertyPath: key,
|
|
1089
1204
|
context: fullContext
|
|
1090
1205
|
};
|
|
1091
|
-
const childEvent = requestEvent.makeChildEvent(
|
|
1092
|
-
|
|
1206
|
+
const childEvent = requestEvent.makeChildEvent(EventType.propertyRequest, prop);
|
|
1207
|
+
let result;
|
|
1208
|
+
let error;
|
|
1209
|
+
if (window.MICapture?.isPreview) this.throwIfDependencyCycleDetected(property);
|
|
1210
|
+
|
|
1211
|
+
try {
|
|
1212
|
+
result = property.compute(fullContext, childEvent);
|
|
1213
|
+
} catch (e) {
|
|
1214
|
+
error = e;
|
|
1215
|
+
}
|
|
1093
1216
|
|
|
1094
1217
|
if (isPromise(result)) {
|
|
1095
1218
|
throw new PromiseException(result);
|
|
1096
1219
|
}
|
|
1097
1220
|
|
|
1098
|
-
|
|
1221
|
+
try {
|
|
1222
|
+
if (error) {
|
|
1223
|
+
callback(null, error);
|
|
1224
|
+
return;
|
|
1225
|
+
} else {
|
|
1226
|
+
callback(result, null);
|
|
1227
|
+
return result;
|
|
1228
|
+
}
|
|
1229
|
+
} catch (e) {
|
|
1230
|
+
const wrappedError = StudioErrorWrapper(e).setSourceDynamicProperty(prop);
|
|
1231
|
+
throw wrappedError;
|
|
1232
|
+
}
|
|
1099
1233
|
};
|
|
1100
1234
|
}
|
|
1101
1235
|
|
|
1236
|
+
throwIfDependencyCycleDetected(property) {
|
|
1237
|
+
performance.now();
|
|
1238
|
+
const hasDependentProperties = property.dependentProperties.size;
|
|
1239
|
+
|
|
1240
|
+
if (hasDependentProperties) {
|
|
1241
|
+
const dependencyCycleProperties = this.getDependencyCycle(property.dependentProperties);
|
|
1242
|
+
const isDependencyCycleDetected = dependencyCycleProperties.length;
|
|
1243
|
+
|
|
1244
|
+
if (isDependencyCycleDetected) {
|
|
1245
|
+
throw new Error(`Dependency cycle detected: ${dependencyCycleProperties.map(prop => {
|
|
1246
|
+
return prop.grouping ? prop.grouping + '::' + prop.propertyKey : prop.propertyKey;
|
|
1247
|
+
}).join(' > ')}`);
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
getDependencyCycle(dependencies) {
|
|
1253
|
+
const propsToInspect = [...dependencies.values()];
|
|
1254
|
+
const propsInspected = new Set();
|
|
1255
|
+
const propsCompleted = new Set();
|
|
1256
|
+
|
|
1257
|
+
while (propsToInspect.length) {
|
|
1258
|
+
const currentProperty = propsToInspect.pop();
|
|
1259
|
+
const detectionResult = this.detectCycle(currentProperty, propsInspected, propsCompleted);
|
|
1260
|
+
if (detectionResult.length) return [currentProperty, ...detectionResult];
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
return [];
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
detectCycle(currentProperty, propsInspected, propsCompleted) {
|
|
1267
|
+
if (!propsCompleted.has(currentProperty)) {
|
|
1268
|
+
propsInspected.add(currentProperty);
|
|
1269
|
+
propsCompleted.add(currentProperty);
|
|
1270
|
+
|
|
1271
|
+
for (const prop of currentProperty.dependencies) {
|
|
1272
|
+
if (!propsCompleted.has(prop)) {
|
|
1273
|
+
const detectionResult = this.detectCycle(prop, propsInspected, propsCompleted);
|
|
1274
|
+
if (detectionResult.length) return [prop, ...detectionResult];
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
if (propsInspected.has(prop)) return [prop];
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
propsInspected.delete(currentProperty);
|
|
1282
|
+
return [];
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1102
1285
|
generateComputeArgs(passedContext = {}, requestEvent) {
|
|
1103
1286
|
const context = contextAccessor(passedContext, key => this.memoizeCache.addContextKey(key));
|
|
1104
1287
|
const getProperty = this.getPropertyProxy(passedContext, requestEvent);
|
|
@@ -1128,7 +1311,7 @@ class Property {
|
|
|
1128
1311
|
const overwrittenResult = overrideFn(result, context);
|
|
1129
1312
|
|
|
1130
1313
|
if (overrideFn !== DEFAULT_OVERRIDE) {
|
|
1131
|
-
const overrideEvent = event.makeChildEvent(
|
|
1314
|
+
const overrideEvent = event.makeChildEvent(EventType.override);
|
|
1132
1315
|
overrideEvent.setValue(result);
|
|
1133
1316
|
}
|
|
1134
1317
|
|
|
@@ -1147,7 +1330,7 @@ class Property {
|
|
|
1147
1330
|
};
|
|
1148
1331
|
const wrappedError = StudioErrorWrapper(error).setSourceDynamicProperty(dynamicProperty).setEntryDynamicProperty(dynamicProperty);
|
|
1149
1332
|
this.memoizeCache.setError(context, wrappedError);
|
|
1150
|
-
event.makeChildEvent(
|
|
1333
|
+
event.makeChildEvent(EventType.error);
|
|
1151
1334
|
event.setError(wrappedError);
|
|
1152
1335
|
throw wrappedError;
|
|
1153
1336
|
}
|
|
@@ -1155,7 +1338,7 @@ class Property {
|
|
|
1155
1338
|
async resolvePromiseResult(promise, context, event) {
|
|
1156
1339
|
try {
|
|
1157
1340
|
const result = await promise;
|
|
1158
|
-
event.makeChildEvent(
|
|
1341
|
+
event.makeChildEvent(EventType.resolve);
|
|
1159
1342
|
const overwrittenResult = this.overrideResult(result, context, event);
|
|
1160
1343
|
this.memoizeCache.set(context, overwrittenResult);
|
|
1161
1344
|
event.setValue(overwrittenResult);
|
|
@@ -1167,7 +1350,7 @@ class Property {
|
|
|
1167
1350
|
|
|
1168
1351
|
async yieldPromiseException(exception, context, event) {
|
|
1169
1352
|
try {
|
|
1170
|
-
event.makeChildEvent(
|
|
1353
|
+
event.makeChildEvent(EventType.await);
|
|
1171
1354
|
await exception.promise;
|
|
1172
1355
|
return this.trySyncCompute(context, event);
|
|
1173
1356
|
} catch (error) {
|
|
@@ -1181,10 +1364,10 @@ class Property {
|
|
|
1181
1364
|
const result = this.computeFn(computeArgs);
|
|
1182
1365
|
|
|
1183
1366
|
if (isPromise(result)) {
|
|
1184
|
-
event.makeChildEvent(
|
|
1367
|
+
event.makeChildEvent(EventType.await);
|
|
1185
1368
|
return this.resolvePromiseResult(result, context, event);
|
|
1186
1369
|
} else {
|
|
1187
|
-
event.makeChildEvent(
|
|
1370
|
+
event.makeChildEvent(EventType.resolve);
|
|
1188
1371
|
const overwrittenResult = this.overrideResult(result, context, event);
|
|
1189
1372
|
this.memoizeCache.set(context, overwrittenResult);
|
|
1190
1373
|
event.setValue(overwrittenResult);
|
|
@@ -1198,7 +1381,7 @@ class Property {
|
|
|
1198
1381
|
cachedCompute(context, event) {
|
|
1199
1382
|
// If memoize cache is not set up, compute compute and set up the cache.
|
|
1200
1383
|
if (this.memoizeCache.has(context)) {
|
|
1201
|
-
event.makeChildEvent(
|
|
1384
|
+
event.makeChildEvent(EventType.cacheRead);
|
|
1202
1385
|
return this.memoizeCache.get(context);
|
|
1203
1386
|
} // Immediately cache the response (it wil be re-written when finalized if it's a promise).
|
|
1204
1387
|
|
|
@@ -1291,7 +1474,7 @@ class GroupedRegistry {
|
|
|
1291
1474
|
}
|
|
1292
1475
|
|
|
1293
1476
|
const {
|
|
1294
|
-
entries
|
|
1477
|
+
entries
|
|
1295
1478
|
} = Object;
|
|
1296
1479
|
|
|
1297
1480
|
function isComputeFn(fn) {
|
|
@@ -1306,13 +1489,13 @@ class AsyncComputed {
|
|
|
1306
1489
|
|
|
1307
1490
|
_defineProperty(this, "globProperties", new GroupedRegistry());
|
|
1308
1491
|
|
|
1309
|
-
_defineProperty(this, "
|
|
1492
|
+
_defineProperty(this, "eventsEnabled", false);
|
|
1310
1493
|
|
|
1311
|
-
_defineProperty(this, "
|
|
1494
|
+
_defineProperty(this, "eventsTree", []);
|
|
1312
1495
|
}
|
|
1313
1496
|
|
|
1314
|
-
|
|
1315
|
-
this.
|
|
1497
|
+
enableEvents() {
|
|
1498
|
+
this.eventsEnabled = true;
|
|
1316
1499
|
}
|
|
1317
1500
|
|
|
1318
1501
|
setProperty(...args) {
|
|
@@ -1331,7 +1514,7 @@ class AsyncComputed {
|
|
|
1331
1514
|
}
|
|
1332
1515
|
|
|
1333
1516
|
setProperties(object, prefix) {
|
|
1334
|
-
entries
|
|
1517
|
+
entries(object).forEach(([path, value]) => {
|
|
1335
1518
|
const fullPath = prefix ? `${prefix}.${path}` : path;
|
|
1336
1519
|
this.setProperty(fullPath, value);
|
|
1337
1520
|
});
|
|
@@ -1347,8 +1530,8 @@ class AsyncComputed {
|
|
|
1347
1530
|
return result;
|
|
1348
1531
|
}
|
|
1349
1532
|
|
|
1350
|
-
get
|
|
1351
|
-
return this.
|
|
1533
|
+
get propertyEvents() {
|
|
1534
|
+
return this.eventsTree;
|
|
1352
1535
|
}
|
|
1353
1536
|
|
|
1354
1537
|
getPropertyInstance(grouping, path) {
|
|
@@ -1419,14 +1602,14 @@ class AsyncComputed {
|
|
|
1419
1602
|
|
|
1420
1603
|
let requestEvent;
|
|
1421
1604
|
|
|
1422
|
-
if (this.
|
|
1423
|
-
requestEvent = createEvent(
|
|
1605
|
+
if (this.eventsEnabled) {
|
|
1606
|
+
requestEvent = createEvent(EventType.propertyRequest, {
|
|
1424
1607
|
propertyGroupKey: property.grouping,
|
|
1425
1608
|
// make sure we're using the property's actual grouping
|
|
1426
1609
|
propertyPath: path,
|
|
1427
1610
|
context: context
|
|
1428
1611
|
});
|
|
1429
|
-
this.
|
|
1612
|
+
this.eventsTree.push(requestEvent);
|
|
1430
1613
|
} else {
|
|
1431
1614
|
requestEvent = createInertEvent();
|
|
1432
1615
|
}
|
|
@@ -1530,7 +1713,7 @@ function trimTextOverflow(element) {
|
|
|
1530
1713
|
const parentElement = element.parentElement;
|
|
1531
1714
|
const parentBox = parentElement.getBoundingClientRect(); // It fits already; no need to resize.
|
|
1532
1715
|
|
|
1533
|
-
if (!overflowsParent(element, parentBox)) {
|
|
1716
|
+
if (!overflowsParent$1(element, parentBox)) {
|
|
1534
1717
|
return;
|
|
1535
1718
|
}
|
|
1536
1719
|
|
|
@@ -1555,7 +1738,7 @@ function truncateText(element, parentBox) {
|
|
|
1555
1738
|
element.parentElement.nextElementSibling.remove();
|
|
1556
1739
|
}
|
|
1557
1740
|
|
|
1558
|
-
while (endPos > 0 && overflowsParent(element, parentBox)) {
|
|
1741
|
+
while (endPos > 0 && overflowsParent$1(element, parentBox)) {
|
|
1559
1742
|
endPos = currentText.lastIndexOf(' ');
|
|
1560
1743
|
currentText = currentText.substr(0, endPos);
|
|
1561
1744
|
|
|
@@ -1586,7 +1769,7 @@ function findOverlappingElement(element, parentBox) {
|
|
|
1586
1769
|
const children = Array.from(element.children);
|
|
1587
1770
|
|
|
1588
1771
|
for (const child of children) {
|
|
1589
|
-
if (overflowsParent(child, parentBox)) {
|
|
1772
|
+
if (overflowsParent$1(child, parentBox)) {
|
|
1590
1773
|
return findOverlappingElement(child, parentBox);
|
|
1591
1774
|
}
|
|
1592
1775
|
} // if no child is found to overlap, return self.
|
|
@@ -1595,14 +1778,14 @@ function findOverlappingElement(element, parentBox) {
|
|
|
1595
1778
|
return element;
|
|
1596
1779
|
}
|
|
1597
1780
|
|
|
1598
|
-
function overflowsParent(element, parentBox) {
|
|
1781
|
+
function overflowsParent$1(element, parentBox) {
|
|
1599
1782
|
const selfBox = element.getBoundingClientRect();
|
|
1600
1783
|
const isOutside = !(selfBox.left >= parentBox.left && selfBox.right <= parentBox.right && selfBox.bottom <= parentBox.bottom && element.scrollHeight <= parentBox.height && element.scrollWidth <= parentBox.width);
|
|
1601
1784
|
return isOutside;
|
|
1602
1785
|
}
|
|
1603
1786
|
|
|
1604
1787
|
const {
|
|
1605
|
-
min
|
|
1788
|
+
min: min$1
|
|
1606
1789
|
} = Math;
|
|
1607
1790
|
function convertToEms(insertProperties, baseFontSize) {
|
|
1608
1791
|
return insertProperties.map(prop => {
|
|
@@ -1623,16 +1806,16 @@ function shrinkToFit(element, richTextStructure, baseFontSize, minFontSize) {
|
|
|
1623
1806
|
} = element;
|
|
1624
1807
|
const parentBox = parentElement.getBoundingClientRect(); // It fits already; no need to resize.
|
|
1625
1808
|
|
|
1626
|
-
if (!overflowsParent
|
|
1809
|
+
if (!overflowsParent(parentBox, element)) {
|
|
1627
1810
|
return true;
|
|
1628
1811
|
}
|
|
1629
1812
|
|
|
1630
1813
|
const smallestFontRatio = richTextStructure.reduce((smallest, op) => {
|
|
1631
|
-
smallest = min(smallest, getFontRatio(op));
|
|
1814
|
+
smallest = min$1(smallest, getFontRatio(op));
|
|
1632
1815
|
|
|
1633
1816
|
if (op.spans) {
|
|
1634
1817
|
for (const span of op.spans) {
|
|
1635
|
-
smallest = min(smallest, getFontRatio(span));
|
|
1818
|
+
smallest = min$1(smallest, getFontRatio(span));
|
|
1636
1819
|
}
|
|
1637
1820
|
}
|
|
1638
1821
|
|
|
@@ -1658,7 +1841,7 @@ function resizeToFit(currentFontSize, selfElement, parentBox, minimumFontSize, s
|
|
|
1658
1841
|
|
|
1659
1842
|
selfElement.style.fontSize = `${currentFontSize}px`; // Re-run if still outside of parent container
|
|
1660
1843
|
|
|
1661
|
-
if (overflowsParent
|
|
1844
|
+
if (overflowsParent(parentBox, selfElement)) {
|
|
1662
1845
|
// truncate if min font size reached
|
|
1663
1846
|
const nextFontSize = currentFontSize - 1;
|
|
1664
1847
|
return resizeToFit(nextFontSize, selfElement, parentBox, minimumFontSize, smallestRatio);
|
|
@@ -1667,7 +1850,7 @@ function resizeToFit(currentFontSize, selfElement, parentBox, minimumFontSize, s
|
|
|
1667
1850
|
return true;
|
|
1668
1851
|
}
|
|
1669
1852
|
|
|
1670
|
-
function overflowsParent
|
|
1853
|
+
function overflowsParent(parentBox, selfElement) {
|
|
1671
1854
|
const range = document.createRange();
|
|
1672
1855
|
range.selectNode(selfElement);
|
|
1673
1856
|
const selfBox = range.getBoundingClientRect();
|
|
@@ -1707,7 +1890,7 @@ const DEFAULT_P_STYLES = {
|
|
|
1707
1890
|
padding: 0
|
|
1708
1891
|
};
|
|
1709
1892
|
const {
|
|
1710
|
-
min
|
|
1893
|
+
min
|
|
1711
1894
|
} = Math;
|
|
1712
1895
|
function makeRenderStructure(ops, fitToOneLine) {
|
|
1713
1896
|
const paragraphs = [];
|
|
@@ -1794,7 +1977,7 @@ function getMinFontSize(ops, defaultSize) {
|
|
|
1794
1977
|
const fontSize = op.attributes && op.attributes.fontSize;
|
|
1795
1978
|
|
|
1796
1979
|
if (fontSize) {
|
|
1797
|
-
return min
|
|
1980
|
+
return min(curMin, parseFloat(fontSize.toString()));
|
|
1798
1981
|
}
|
|
1799
1982
|
|
|
1800
1983
|
return curMin;
|
|
@@ -1959,7 +2142,12 @@ function ImageTag({
|
|
|
1959
2142
|
throw new Error('Could not render image as no URL was provided');
|
|
1960
2143
|
}
|
|
1961
2144
|
|
|
1962
|
-
|
|
2145
|
+
const isDataURL = imageUrl.match(/^data:/);
|
|
2146
|
+
|
|
2147
|
+
if (!isDataURL) {
|
|
2148
|
+
CD.waitForAsset(imageUrl);
|
|
2149
|
+
}
|
|
2150
|
+
|
|
1963
2151
|
const styles = {
|
|
1964
2152
|
height: '100%',
|
|
1965
2153
|
width: '100%',
|
|
@@ -2001,13 +2189,22 @@ const HIDDEN_IMAGE_STYLE = {
|
|
|
2001
2189
|
position: 'absolute',
|
|
2002
2190
|
opacity: 0
|
|
2003
2191
|
};
|
|
2004
|
-
function stylesForImage(imageUrl, cropStyle
|
|
2192
|
+
function stylesForImage(imageUrl, cropStyle, imageAnchor = {
|
|
2193
|
+
horizontalPosition: 'left',
|
|
2194
|
+
verticalPosition: 'top'
|
|
2195
|
+
}) {
|
|
2005
2196
|
const cropStyles = CROPPING_OPTIONS[cropStyle];
|
|
2006
|
-
|
|
2197
|
+
const {
|
|
2198
|
+
horizontalPosition,
|
|
2199
|
+
verticalPosition
|
|
2200
|
+
} = imageAnchor;
|
|
2201
|
+
const imageStyles = {
|
|
2007
2202
|
background: `url("${imageUrl}")`,
|
|
2008
2203
|
...BASE_STYLES,
|
|
2009
2204
|
...cropStyles
|
|
2010
2205
|
};
|
|
2206
|
+
imageStyles.backgroundPosition = `${horizontalPosition} ${verticalPosition}`;
|
|
2207
|
+
return imageStyles;
|
|
2011
2208
|
}
|
|
2012
2209
|
|
|
2013
2210
|
class DynamicImageTag extends StudioTool {
|
|
@@ -2024,15 +2221,21 @@ class DynamicImageTag extends StudioTool {
|
|
|
2024
2221
|
tag: {
|
|
2025
2222
|
dynamicProperty,
|
|
2026
2223
|
isCropped,
|
|
2027
|
-
dynamicAltText
|
|
2224
|
+
dynamicAltText,
|
|
2225
|
+
imageAnchor
|
|
2028
2226
|
},
|
|
2029
2227
|
getPropertyWithFallback
|
|
2030
2228
|
} = this.props;
|
|
2031
2229
|
const src = getPropertyWithFallback(dynamicProperty);
|
|
2032
2230
|
const altText = getPropertyWithFallback(dynamicAltText, '');
|
|
2033
|
-
|
|
2231
|
+
const isDataURL = src.match(/^data:/);
|
|
2232
|
+
|
|
2233
|
+
if (!isDataURL) {
|
|
2234
|
+
CD.waitForAsset(src);
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2034
2237
|
const styleType = isCropped ? 'cropped' : 'contained';
|
|
2035
|
-
const styles = stylesForImage(src, styleType);
|
|
2238
|
+
const styles = stylesForImage(src, styleType, imageAnchor);
|
|
2036
2239
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
2037
2240
|
className: "studio-dynamic-image",
|
|
2038
2241
|
role: "image",
|
|
@@ -2140,6 +2343,7 @@ class App extends React.Component {
|
|
|
2140
2343
|
canvas: canvas
|
|
2141
2344
|
}, /*#__PURE__*/React.createElement(Tags, {
|
|
2142
2345
|
tags: tags || [],
|
|
2346
|
+
canvas: canvas,
|
|
2143
2347
|
registryResolver: registryResolver,
|
|
2144
2348
|
propertyResolver: propertyResolver,
|
|
2145
2349
|
onPendingPromise: this.onPendingPromise
|
|
@@ -2304,12 +2508,15 @@ function makeCustomTool(toolData) {
|
|
|
2304
2508
|
} = this.props;
|
|
2305
2509
|
const {
|
|
2306
2510
|
code,
|
|
2307
|
-
propertyInputs = []
|
|
2511
|
+
propertyInputs = [],
|
|
2512
|
+
context_options: contextOptionsInputs = []
|
|
2308
2513
|
} = toolData;
|
|
2309
2514
|
const propertyNames = propertyInputs.map(input => input.variableName);
|
|
2310
|
-
const
|
|
2311
|
-
const
|
|
2312
|
-
|
|
2515
|
+
const contextOptionsNames = contextOptionsInputs.map(input => input.name);
|
|
2516
|
+
const Tool = new Function(...propertyNames, ...contextOptionsNames, 'html', 'CD', 'tag', code);
|
|
2517
|
+
const propertyValues = propertyInputs.map(prop => getPropertyWithFallback(prop));
|
|
2518
|
+
const contextValues = contextOptionsInputs.map(input => tag.toolProperties[input.name]);
|
|
2519
|
+
return Tool(...propertyValues, ...contextValues, html, CD, tag);
|
|
2313
2520
|
}
|
|
2314
2521
|
|
|
2315
2522
|
};
|
|
@@ -2343,9 +2550,9 @@ function cleanHTML(element) {
|
|
|
2343
2550
|
newBody.style.cssText = BASE_STYLE;
|
|
2344
2551
|
newBody.appendChild(element);
|
|
2345
2552
|
|
|
2346
|
-
if (analyticsLength >
|
|
2553
|
+
if (analyticsLength > 500) {
|
|
2347
2554
|
analytics.setAttribute('data-mi-data', '{}');
|
|
2348
|
-
console.log('extraData trying to be set exceeds
|
|
2555
|
+
console.log('extraData trying to be set exceeds 500 characters, setting extraData to be empty to avoid breaking crops');
|
|
2349
2556
|
}
|
|
2350
2557
|
|
|
2351
2558
|
if (analytics) {
|
|
@@ -2382,6 +2589,85 @@ function addBrowserContent(baseElement) {
|
|
|
2382
2589
|
rootNode.body.appendChild(script);
|
|
2383
2590
|
}
|
|
2384
2591
|
|
|
2592
|
+
const COUNT_OF_SCRIPT_TAGS_COMPILED_BY_STUDIO = 5;
|
|
2593
|
+
|
|
2594
|
+
const stringMatch = (original, comparable, ignoreRegExp) => {
|
|
2595
|
+
return original.replace(ignoreRegExp, '') === comparable;
|
|
2596
|
+
};
|
|
2597
|
+
|
|
2598
|
+
const studioOverwritableJs = 'var app = new studio[a-zA-Z0-9]*.A\\(\\);';
|
|
2599
|
+
const jsIgnoreRE = new RegExp(`\\s|${studioOverwritableJs}`, 'g');
|
|
2600
|
+
const jsCompareString = `(function(){app.render(document.getElementById('react-root')).then(function(){window.APP_SUCCESSFULLY_RENDERED=true;});})();`;
|
|
2601
|
+
const isPristinePicJsTag = scriptTag => {
|
|
2602
|
+
const script = scriptTag.innerHTML;
|
|
2603
|
+
return stringMatch(script, jsCompareString, jsIgnoreRE);
|
|
2604
|
+
};
|
|
2605
|
+
const isDocumentEligibleForStaticHandling = rootNode => {
|
|
2606
|
+
const document = getDocumentNode(rootNode);
|
|
2607
|
+
const scriptTags = document.getElementsByTagName('script');
|
|
2608
|
+
const hasTagContainingPristinePicJs = Array.from(scriptTags).some(isPristinePicJsTag);
|
|
2609
|
+
|
|
2610
|
+
if (!hasTagContainingPristinePicJs) {
|
|
2611
|
+
console.log('static status is false - user-altered js detected');
|
|
2612
|
+
return false;
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2615
|
+
if (scriptTags.length > COUNT_OF_SCRIPT_TAGS_COMPILED_BY_STUDIO) {
|
|
2616
|
+
console.log('static status is false - user-added script tags detected');
|
|
2617
|
+
return false;
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2620
|
+
return true;
|
|
2621
|
+
};
|
|
2622
|
+
|
|
2623
|
+
const basicTypes = new Set(['group', 'image', 'rectangle', 'richText', 'staticPic', 'text']);
|
|
2624
|
+
|
|
2625
|
+
const isTagStatic = tag => {
|
|
2626
|
+
const {
|
|
2627
|
+
appliedElementModifiers,
|
|
2628
|
+
conditionalDynamicProperty,
|
|
2629
|
+
dynamicAltText,
|
|
2630
|
+
dynamicProperty,
|
|
2631
|
+
richText,
|
|
2632
|
+
subtags,
|
|
2633
|
+
type
|
|
2634
|
+
} = tag;
|
|
2635
|
+
if (subtags?.length) return subtags.some(isTagStatic);
|
|
2636
|
+
const isCustomTool = type.startsWith('customTool.');
|
|
2637
|
+
const hasDynamicRichText = richText?.some(({
|
|
2638
|
+
insert
|
|
2639
|
+
}) => typeof insert === 'object' && insert.dynamicProperty);
|
|
2640
|
+
if (appliedElementModifiers || !basicTypes.has(type) || conditionalDynamicProperty || dynamicAltText || dynamicProperty || hasDynamicRichText || isCustomTool) return false;
|
|
2641
|
+
return true;
|
|
2642
|
+
};
|
|
2643
|
+
|
|
2644
|
+
const areAttributesStatic = attributes => {
|
|
2645
|
+
const {
|
|
2646
|
+
canvases
|
|
2647
|
+
} = attributes;
|
|
2648
|
+
|
|
2649
|
+
for (const {
|
|
2650
|
+
appliedElementModifiers,
|
|
2651
|
+
tags = [],
|
|
2652
|
+
clickthroughDynamicProperty,
|
|
2653
|
+
conditionalDynamicProperty
|
|
2654
|
+
} of canvases) {
|
|
2655
|
+
if (appliedElementModifiers || clickthroughDynamicProperty || conditionalDynamicProperty) {
|
|
2656
|
+
console.log('static status is false - dynamic properties on canvas detected');
|
|
2657
|
+
return false;
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2660
|
+
for (const tag of tags) {
|
|
2661
|
+
if (!isTagStatic(tag)) {
|
|
2662
|
+
console.log('static status is false - dynamic properties on tag detected');
|
|
2663
|
+
return false;
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2668
|
+
return true;
|
|
2669
|
+
};
|
|
2670
|
+
|
|
2385
2671
|
class StudioFramework {
|
|
2386
2672
|
constructor(opts = setupAppDefaults()) {
|
|
2387
2673
|
_defineProperty(this, "currentGrouping", false);
|
|
@@ -2406,22 +2692,40 @@ class StudioFramework {
|
|
|
2406
2692
|
|
|
2407
2693
|
_defineProperty(this, "debug", {
|
|
2408
2694
|
CD,
|
|
2695
|
+
enableDebugMode: () => {
|
|
2696
|
+
this.asyncComputed.enableEvents();
|
|
2697
|
+
},
|
|
2409
2698
|
getAllProperties: () => this.asyncComputed.dumpState(),
|
|
2410
|
-
getPropertyEvents: () =>
|
|
2699
|
+
getPropertyEvents: () => {
|
|
2700
|
+
console.warn('`app.debug.getPropertyEvents()` is deprecated. Please use `app.meta.enableEvents()` and `app.meta.getEvents([consoleLog])`.');
|
|
2701
|
+
return this.asyncComputed.propertyEvents;
|
|
2702
|
+
},
|
|
2411
2703
|
logProperties: () => {
|
|
2412
2704
|
const state = this.asyncComputed.dumpState();
|
|
2413
|
-
console.warn('`app.debug.logProperties()` is deprecated. Please use `app.
|
|
2705
|
+
console.warn('`app.debug.logProperties()` is deprecated. Please use `app.meta.enableEvents` and `app.meta.getEvents([consoleLog])`.');
|
|
2414
2706
|
console.log(JSON.stringify(state, null, 2));
|
|
2415
2707
|
},
|
|
2416
|
-
enableDebugMode: () => {
|
|
2417
|
-
this.asyncComputed.enableDebugMode();
|
|
2418
|
-
},
|
|
2419
2708
|
logPropertyTree: () => {
|
|
2420
|
-
const events = this.asyncComputed.
|
|
2709
|
+
const events = this.asyncComputed.propertyEvents;
|
|
2421
2710
|
console.log(JSON.stringify(events, null, 2));
|
|
2422
2711
|
}
|
|
2423
2712
|
});
|
|
2424
2713
|
|
|
2714
|
+
_defineProperty(this, "meta", {
|
|
2715
|
+
eventsEnabled: false,
|
|
2716
|
+
enableEvents: () => {
|
|
2717
|
+
// tbd: options for pruning which events are captured
|
|
2718
|
+
this.meta.eventsEnabled = true;
|
|
2719
|
+
this.asyncComputed.enableEvents();
|
|
2720
|
+
},
|
|
2721
|
+
getEvents: consoleLog => {
|
|
2722
|
+
if (!this.meta.eventsEnabled) console.warn('`app.metadata.getEvents()` was called, however `app.metadata.enableEvents([...options])` was not set first. No events will be returned.');
|
|
2723
|
+
const events = this.asyncComputed.propertyEvents;
|
|
2724
|
+
if (consoleLog) console.log(JSON.stringify(events, null, 2));
|
|
2725
|
+
return events;
|
|
2726
|
+
}
|
|
2727
|
+
});
|
|
2728
|
+
|
|
2425
2729
|
const {
|
|
2426
2730
|
canvases = [],
|
|
2427
2731
|
customProps = [],
|
|
@@ -2434,6 +2738,12 @@ class StudioFramework {
|
|
|
2434
2738
|
namespacedOptions = [],
|
|
2435
2739
|
queryParams = {}
|
|
2436
2740
|
} = opts;
|
|
2741
|
+
|
|
2742
|
+
if (window.MICapture?.isPreview) {
|
|
2743
|
+
console.log('static status is true - static check has started');
|
|
2744
|
+
window.RENDERED_STATICALLY = true;
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2437
2747
|
this.options = options;
|
|
2438
2748
|
this.namespacedOptions = namespacedOptions;
|
|
2439
2749
|
this.customProps = customProps;
|
|
@@ -2451,7 +2761,25 @@ class StudioFramework {
|
|
|
2451
2761
|
return queryParams;
|
|
2452
2762
|
});
|
|
2453
2763
|
animation(this);
|
|
2454
|
-
|
|
2764
|
+
|
|
2765
|
+
if (this.shouldPerformStaticCheck) {
|
|
2766
|
+
const proxy = new Proxy(this, {
|
|
2767
|
+
set(target, key, value) {
|
|
2768
|
+
if (key in target && key !== 'currentGrouping') {
|
|
2769
|
+
window.RENDERED_STATICALLY = false;
|
|
2770
|
+
console.log(`static status is false - overridden StudioFramework class method `, key);
|
|
2771
|
+
}
|
|
2772
|
+
|
|
2773
|
+
return Reflect.set(target, key, value);
|
|
2774
|
+
}
|
|
2775
|
+
|
|
2776
|
+
});
|
|
2777
|
+
this.setup.call(proxy);
|
|
2778
|
+
if (this.shouldPerformStaticCheck) window.RENDERED_STATICALLY = areAttributesStatic(opts);
|
|
2779
|
+
} else {
|
|
2780
|
+
this.setup();
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2455
2783
|
this.setupOptions();
|
|
2456
2784
|
this.setupNamespacedOptions();
|
|
2457
2785
|
this.setupCustomTools();
|
|
@@ -2459,16 +2787,20 @@ class StudioFramework {
|
|
|
2459
2787
|
this.setupModifiedProps();
|
|
2460
2788
|
}
|
|
2461
2789
|
|
|
2790
|
+
get shouldPerformStaticCheck() {
|
|
2791
|
+
return window.MICapture?.isPreview && window.RENDERED_STATICALLY;
|
|
2792
|
+
}
|
|
2793
|
+
|
|
2462
2794
|
triggerRerender() {
|
|
2463
2795
|
if (this.appComponent) {
|
|
2464
2796
|
this.appComponent.forceUpdate();
|
|
2465
2797
|
}
|
|
2466
2798
|
}
|
|
2467
2799
|
|
|
2468
|
-
async
|
|
2800
|
+
async resolveConditionalDynamicProperty(model) {
|
|
2469
2801
|
const {
|
|
2470
2802
|
conditionalDynamicProperty
|
|
2471
|
-
} =
|
|
2803
|
+
} = model;
|
|
2472
2804
|
if (!conditionalDynamicProperty) return [true, null];
|
|
2473
2805
|
const {
|
|
2474
2806
|
propertyGroupKey = '',
|
|
@@ -2485,7 +2817,7 @@ class StudioFramework {
|
|
|
2485
2817
|
} = this;
|
|
2486
2818
|
|
|
2487
2819
|
for (const canvas of canvases) {
|
|
2488
|
-
const [result, error] = await this.
|
|
2820
|
+
const [result, error] = await this.resolveConditionalDynamicProperty(canvas);
|
|
2489
2821
|
if (result) return canvas;
|
|
2490
2822
|
|
|
2491
2823
|
if (error) {
|
|
@@ -2555,28 +2887,41 @@ class StudioFramework {
|
|
|
2555
2887
|
setup() {} // eslint-disable-next-line
|
|
2556
2888
|
|
|
2557
2889
|
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
} // eslint-disable-next-line
|
|
2890
|
+
async getCurrentTags(tags, canvas) {
|
|
2891
|
+
const filteredTags = [];
|
|
2561
2892
|
|
|
2893
|
+
for (const tag of tags) {
|
|
2894
|
+
const [result, error] = await this.resolveConditionalDynamicProperty(tag);
|
|
2562
2895
|
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
} = this.options;
|
|
2896
|
+
if (result) {
|
|
2897
|
+
filteredTags.push(tag);
|
|
2898
|
+
}
|
|
2567
2899
|
|
|
2568
|
-
|
|
2569
|
-
|
|
2900
|
+
if (error) {
|
|
2901
|
+
const wrappedError = StudioErrorWrapper(error, `Skipped ${tag.label || tag.displayName} because conditional dynamic property threw an error`).setSourceType('tag-condition').setSourceDynamicProperty(tag.conditionalDynamicProperty).setEntryDynamicProperty(tag.conditionalDynamicProperty).setTag(tag).setCanvas(canvas);
|
|
2902
|
+
console.warn(wrappedError);
|
|
2903
|
+
}
|
|
2570
2904
|
}
|
|
2571
2905
|
|
|
2572
|
-
|
|
2906
|
+
return this.setupTags(filteredTags);
|
|
2907
|
+
}
|
|
2908
|
+
|
|
2909
|
+
setupTags(tags) {
|
|
2910
|
+
return tags;
|
|
2911
|
+
}
|
|
2912
|
+
|
|
2913
|
+
async clickthrough(currentCanvas) {
|
|
2914
|
+
const canvasCDP = currentCanvas?.clickthroughDynamicProperty;
|
|
2915
|
+
|
|
2916
|
+
if (canvasCDP) {
|
|
2573
2917
|
const {
|
|
2574
2918
|
context,
|
|
2575
2919
|
propertyPath,
|
|
2576
|
-
propertyValue
|
|
2577
|
-
|
|
2920
|
+
propertyValue,
|
|
2921
|
+
propertyGroupKey
|
|
2922
|
+
} = canvasCDP;
|
|
2578
2923
|
if (propertyValue) return propertyValue;
|
|
2579
|
-
const [result, error] = await this.getPropertyTuple(propertyPath, context);
|
|
2924
|
+
const [result, error] = await this.getPropertyTuple(propertyGroupKey, propertyPath, context);
|
|
2580
2925
|
|
|
2581
2926
|
if (error) {
|
|
2582
2927
|
throw StudioErrorWrapper(error).setSourceType('dynamic-clickthrough').setCanvas(currentCanvas);
|
|
@@ -2658,18 +3003,25 @@ class StudioFramework {
|
|
|
2658
3003
|
const {
|
|
2659
3004
|
propertyGroupKey,
|
|
2660
3005
|
propertyPath,
|
|
3006
|
+
propertyValue,
|
|
2661
3007
|
context
|
|
2662
3008
|
} = value;
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
}
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
3009
|
+
|
|
3010
|
+
if (propertyGroupKey === 'static') {
|
|
3011
|
+
this.setProperty(`options.${key}`, propertyValue);
|
|
3012
|
+
this.setProperty(key, propertyValue);
|
|
3013
|
+
} else {
|
|
3014
|
+
this.setProperty(`options.${key}`, ({
|
|
3015
|
+
getProperty
|
|
3016
|
+
}) => {
|
|
3017
|
+
return getProperty(propertyGroupKey, propertyPath, context);
|
|
3018
|
+
});
|
|
3019
|
+
this.setProperty(key, ({
|
|
3020
|
+
getProperty
|
|
3021
|
+
}) => {
|
|
3022
|
+
return getProperty(propertyGroupKey, propertyPath, context);
|
|
3023
|
+
});
|
|
3024
|
+
}
|
|
2673
3025
|
} else {
|
|
2674
3026
|
this.setProperty(`options.${key}`, value);
|
|
2675
3027
|
this.setProperty(key, value);
|
|
@@ -2695,13 +3047,19 @@ class StudioFramework {
|
|
|
2695
3047
|
const {
|
|
2696
3048
|
propertyGroupKey,
|
|
2697
3049
|
propertyPath,
|
|
3050
|
+
propertyValue,
|
|
2698
3051
|
context
|
|
2699
3052
|
} = value;
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
3053
|
+
|
|
3054
|
+
if (propertyGroupKey === 'static') {
|
|
3055
|
+
this.setProperty(`options.${fieldName}`, propertyValue);
|
|
3056
|
+
} else {
|
|
3057
|
+
this.setProperty(`options.${fieldName}`, ({
|
|
3058
|
+
getProperty
|
|
3059
|
+
}) => {
|
|
3060
|
+
return getProperty(propertyGroupKey, propertyPath, context);
|
|
3061
|
+
});
|
|
3062
|
+
}
|
|
2705
3063
|
} else {
|
|
2706
3064
|
this.setProperty(`options.${fieldName}`, value);
|
|
2707
3065
|
}
|
|
@@ -2795,19 +3153,47 @@ class StudioFramework {
|
|
|
2795
3153
|
throw e;
|
|
2796
3154
|
}
|
|
2797
3155
|
|
|
3156
|
+
handleAndPreventFutureAnalyticsCalls(data) {
|
|
3157
|
+
if (typeof data !== 'object') {
|
|
3158
|
+
throw new Error('The result of `analyticsData` must be an object');
|
|
3159
|
+
}
|
|
3160
|
+
|
|
3161
|
+
const format = window.MICapture?.format;
|
|
3162
|
+
const analytics = document.querySelector('#mi-data');
|
|
3163
|
+
|
|
3164
|
+
if (format === 'html') {
|
|
3165
|
+
const analyticsLength = analytics ? (analytics.getAttribute('data-mi-data') || '').length : 0;
|
|
3166
|
+
|
|
3167
|
+
if (analyticsLength > 500) {
|
|
3168
|
+
analytics.setAttribute('data-mi-data', '{}');
|
|
3169
|
+
console.log('extraData trying to be set exceeds 500 characters, setting extraData to be empty to avoid breaking crops');
|
|
3170
|
+
}
|
|
3171
|
+
} // Force a full overwrite
|
|
3172
|
+
|
|
3173
|
+
|
|
3174
|
+
if (analytics) document.querySelector('#mi-data').remove();
|
|
3175
|
+
CD.setExtraData(data);
|
|
3176
|
+
|
|
3177
|
+
CD.setExtraData = () => {
|
|
3178
|
+
console.log('setExtraData call was prevented via handleAndPreventFutureAnalyticsCalls');
|
|
3179
|
+
};
|
|
3180
|
+
|
|
3181
|
+
CD.resume();
|
|
3182
|
+
}
|
|
3183
|
+
|
|
2798
3184
|
async render(targetElement) {
|
|
3185
|
+
if (window.MICapture?.isPreview) console.log('Preview Render');
|
|
2799
3186
|
let currentCanvas;
|
|
2800
3187
|
|
|
2801
3188
|
try {
|
|
2802
|
-
var _currentCanvas;
|
|
2803
|
-
|
|
2804
3189
|
CD.pause();
|
|
2805
3190
|
currentCanvas = await this.getCurrentCanvas();
|
|
2806
3191
|
const clickthroughURL = await this.handleClickthrough(currentCanvas);
|
|
2807
|
-
const canvasTags =
|
|
2808
|
-
const tags = this.
|
|
3192
|
+
const canvasTags = currentCanvas?.tags || [];
|
|
3193
|
+
const tags = await this.getCurrentTags(canvasTags, currentCanvas);
|
|
2809
3194
|
const height = currentCanvas.height || this.options.height;
|
|
2810
3195
|
const width = currentCanvas.width || this.options.width;
|
|
3196
|
+
const format = window.MICapture?.format;
|
|
2811
3197
|
const renderPromise = this.renderApp(targetElement, clickthroughURL, tags, {
|
|
2812
3198
|
height,
|
|
2813
3199
|
width
|
|
@@ -2819,12 +3205,23 @@ class StudioFramework {
|
|
|
2819
3205
|
this.setupAnimation();
|
|
2820
3206
|
}
|
|
2821
3207
|
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
3208
|
+
if (this.shouldPerformStaticCheck) {
|
|
3209
|
+
if (window.RENDERED_STATICALLY = isDocumentEligibleForStaticHandling(targetElement)) {
|
|
3210
|
+
console.log('static status is true - static check has finished');
|
|
3211
|
+
} else {
|
|
3212
|
+
console.log('static status is false - static check has finished');
|
|
3213
|
+
}
|
|
3214
|
+
}
|
|
3215
|
+
|
|
3216
|
+
if (format === 'html') {
|
|
3217
|
+
cleanHTML(targetElement);
|
|
3218
|
+
addBrowserContent(targetElement);
|
|
3219
|
+
}
|
|
2825
3220
|
} catch (e) {
|
|
2826
3221
|
const wrappedError = StudioErrorWrapper(e).setCanvas(currentCanvas);
|
|
2827
3222
|
this.handleRenderError(wrappedError);
|
|
3223
|
+
} finally {
|
|
3224
|
+
CD.resume();
|
|
2828
3225
|
}
|
|
2829
3226
|
}
|
|
2830
3227
|
|
|
@@ -3116,4 +3513,4 @@ if (window.MICapture && window.MICapture.captureAppLog) {
|
|
|
3116
3513
|
}
|
|
3117
3514
|
|
|
3118
3515
|
export default StudioFramework;
|
|
3119
|
-
export { App, StudioTool, computedPath, makeDynamicProperty };
|
|
3516
|
+
export { App, StudioError, StudioTool, computedPath, makeDynamicProperty };
|