@ninetailed/experience.js-react 4.1.0-beta.1 → 4.1.0-beta.3

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 (3) hide show
  1. package/index.cjs +483 -483
  2. package/index.js +484 -484
  3. package/package.json +3 -3
package/index.cjs CHANGED
@@ -5,22 +5,22 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var React = require('react');
7
7
  var experience_js = require('@ninetailed/experience.js');
8
- var _debounce = require('lodash/debounce');
9
- var values$1 = require('lodash/values');
8
+ var reactIntersectionObserver = require('react-intersection-observer');
10
9
  var experience_jsShared = require('@ninetailed/experience.js-shared');
11
10
  var isEqual = require('lodash/isEqual');
12
- var reactIntersectionObserver = require('react-intersection-observer');
13
- var get$1 = require('lodash/get');
14
11
  var has$1 = require('lodash/has');
12
+ var _debounce = require('lodash/debounce');
13
+ var values$1 = require('lodash/values');
14
+ var get$1 = require('lodash/get');
15
15
 
16
16
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
17
17
 
18
18
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
19
+ var isEqual__default = /*#__PURE__*/_interopDefaultLegacy(isEqual);
20
+ var has__default = /*#__PURE__*/_interopDefaultLegacy(has$1);
19
21
  var _debounce__default = /*#__PURE__*/_interopDefaultLegacy(_debounce);
20
22
  var values__default = /*#__PURE__*/_interopDefaultLegacy(values$1);
21
- var isEqual__default = /*#__PURE__*/_interopDefaultLegacy(isEqual);
22
23
  var get__default = /*#__PURE__*/_interopDefaultLegacy(get$1);
23
- var has__default = /*#__PURE__*/_interopDefaultLegacy(has$1);
24
24
 
25
25
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
26
26
 
@@ -1107,86 +1107,6 @@ $$3({ target: 'Object', stat: true, arity: 2, forced: Object.assign !== assign }
1107
1107
 
1108
1108
  const NinetailedContext = /*#__PURE__*/React.createContext(undefined);
1109
1109
 
1110
- const ExperimentsContext = /*#__PURE__*/React.createContext(undefined);
1111
-
1112
- var aCallable = aCallable$2;
1113
- var toObject$1 = toObject$4;
1114
- var IndexedObject = indexedObject;
1115
- var lengthOfArrayLike = lengthOfArrayLike$2;
1116
-
1117
- var $TypeError$1 = TypeError;
1118
-
1119
- // `Array.prototype.{ reduce, reduceRight }` methods implementation
1120
- var createMethod = function (IS_RIGHT) {
1121
- return function (that, callbackfn, argumentsLength, memo) {
1122
- aCallable(callbackfn);
1123
- var O = toObject$1(that);
1124
- var self = IndexedObject(O);
1125
- var length = lengthOfArrayLike(O);
1126
- var index = IS_RIGHT ? length - 1 : 0;
1127
- var i = IS_RIGHT ? -1 : 1;
1128
- if (argumentsLength < 2) while (true) {
1129
- if (index in self) {
1130
- memo = self[index];
1131
- index += i;
1132
- break;
1133
- }
1134
- index += i;
1135
- if (IS_RIGHT ? index < 0 : length <= index) {
1136
- throw $TypeError$1('Reduce of empty array with no initial value');
1137
- }
1138
- }
1139
- for (;IS_RIGHT ? index >= 0 : length > index; index += i) if (index in self) {
1140
- memo = callbackfn(memo, self[index], index, O);
1141
- }
1142
- return memo;
1143
- };
1144
- };
1145
-
1146
- var arrayReduce = {
1147
- // `Array.prototype.reduce` method
1148
- // https://tc39.es/ecma262/#sec-array.prototype.reduce
1149
- left: createMethod(false),
1150
- // `Array.prototype.reduceRight` method
1151
- // https://tc39.es/ecma262/#sec-array.prototype.reduceright
1152
- right: createMethod(true)
1153
- };
1154
-
1155
- var fails$2 = fails$c;
1156
-
1157
- var arrayMethodIsStrict$1 = function (METHOD_NAME, argument) {
1158
- var method = [][METHOD_NAME];
1159
- return !!method && fails$2(function () {
1160
- // eslint-disable-next-line no-useless-call -- required for testing
1161
- method.call(null, argument || function () { return 1; }, 1);
1162
- });
1163
- };
1164
-
1165
- var classof$2 = classofRaw$1;
1166
- var global$3 = global$d;
1167
-
1168
- var engineIsNode = classof$2(global$3.process) == 'process';
1169
-
1170
- var $$2 = _export;
1171
- var $reduce = arrayReduce.left;
1172
- var arrayMethodIsStrict = arrayMethodIsStrict$1;
1173
- var CHROME_VERSION = engineV8Version;
1174
- var IS_NODE = engineIsNode;
1175
-
1176
- var STRICT_METHOD = arrayMethodIsStrict('reduce');
1177
- // Chrome 80-82 has a critical bug
1178
- // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
1179
- var CHROME_BUG = !IS_NODE && CHROME_VERSION > 79 && CHROME_VERSION < 83;
1180
-
1181
- // `Array.prototype.reduce` method
1182
- // https://tc39.es/ecma262/#sec-array.prototype.reduce
1183
- $$2({ target: 'Array', proto: true, forced: !STRICT_METHOD || CHROME_BUG }, {
1184
- reduce: function reduce(callbackfn /* , initialValue */) {
1185
- var length = arguments.length;
1186
- return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : undefined);
1187
- }
1188
- });
1189
-
1190
1110
  var objectDefineProperties = {};
1191
1111
 
1192
1112
  var DESCRIPTORS$2 = descriptors;
@@ -1322,9 +1242,9 @@ var addToUnscopables$1 = function (key) {
1322
1242
 
1323
1243
  var iterators = {};
1324
1244
 
1325
- var fails$1 = fails$c;
1245
+ var fails$2 = fails$c;
1326
1246
 
1327
- var correctPrototypeGetter = !fails$1(function () {
1247
+ var correctPrototypeGetter = !fails$2(function () {
1328
1248
  function F() { /* empty */ }
1329
1249
  F.prototype.constructor = null;
1330
1250
  // eslint-disable-next-line es/no-object-getprototypeof -- required for testing
@@ -1333,7 +1253,7 @@ var correctPrototypeGetter = !fails$1(function () {
1333
1253
 
1334
1254
  var hasOwn$2 = hasOwnProperty_1;
1335
1255
  var isCallable$5 = isCallable$g;
1336
- var toObject = toObject$4;
1256
+ var toObject$1 = toObject$4;
1337
1257
  var sharedKey = sharedKey$3;
1338
1258
  var CORRECT_PROTOTYPE_GETTER = correctPrototypeGetter;
1339
1259
 
@@ -1345,7 +1265,7 @@ var ObjectPrototype = $Object$1.prototype;
1345
1265
  // https://tc39.es/ecma262/#sec-object.getprototypeof
1346
1266
  // eslint-disable-next-line es/no-object-getprototypeof -- safe
1347
1267
  var objectGetPrototypeOf = CORRECT_PROTOTYPE_GETTER ? $Object$1.getPrototypeOf : function (O) {
1348
- var object = toObject(O);
1268
+ var object = toObject$1(O);
1349
1269
  if (hasOwn$2(object, IE_PROTO)) return object[IE_PROTO];
1350
1270
  var constructor = object.constructor;
1351
1271
  if (isCallable$5(constructor) && object instanceof constructor) {
@@ -1353,7 +1273,7 @@ var objectGetPrototypeOf = CORRECT_PROTOTYPE_GETTER ? $Object$1.getPrototypeOf :
1353
1273
  } return object instanceof $Object$1 ? ObjectPrototype : null;
1354
1274
  };
1355
1275
 
1356
- var fails = fails$c;
1276
+ var fails$1 = fails$c;
1357
1277
  var isCallable$4 = isCallable$g;
1358
1278
  var isObject = isObject$6;
1359
1279
  var getPrototypeOf$1 = objectGetPrototypeOf;
@@ -1378,7 +1298,7 @@ if ([].keys) {
1378
1298
  }
1379
1299
  }
1380
1300
 
1381
- var NEW_ITERATOR_PROTOTYPE = !isObject(IteratorPrototype$2) || fails(function () {
1301
+ var NEW_ITERATOR_PROTOTYPE = !isObject(IteratorPrototype$2) || fails$1(function () {
1382
1302
  var test = {};
1383
1303
  // FF44- legacy iterators case
1384
1304
  return IteratorPrototype$2[ITERATOR$2].call(test) !== test;
@@ -1431,11 +1351,11 @@ var iteratorCreateConstructor = function (IteratorConstructor, NAME, next, ENUME
1431
1351
  var isCallable$3 = isCallable$g;
1432
1352
 
1433
1353
  var $String$1 = String;
1434
- var $TypeError = TypeError;
1354
+ var $TypeError$1 = TypeError;
1435
1355
 
1436
1356
  var aPossiblePrototype$1 = function (argument) {
1437
1357
  if (typeof argument == 'object' || isCallable$3(argument)) return argument;
1438
- throw $TypeError("Can't set " + $String$1(argument) + ' as a prototype');
1358
+ throw $TypeError$1("Can't set " + $String$1(argument) + ' as a prototype');
1439
1359
  };
1440
1360
 
1441
1361
  /* eslint-disable no-proto -- safe */
@@ -1467,7 +1387,7 @@ var objectSetPrototypeOf = Object.setPrototypeOf || ('__proto__' in {} ? functio
1467
1387
  };
1468
1388
  }() : undefined);
1469
1389
 
1470
- var $$1 = _export;
1390
+ var $$2 = _export;
1471
1391
  var call = functionCall;
1472
1392
  var FunctionName = functionName;
1473
1393
  var isCallable$2 = isCallable$g;
@@ -1552,7 +1472,7 @@ var iteratorDefine = function (Iterable, NAME, IteratorConstructor, next, DEFAUL
1552
1472
  if (BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {
1553
1473
  defineBuiltIn(IterablePrototype, KEY, methods[KEY]);
1554
1474
  }
1555
- } else $$1({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods);
1475
+ } else $$2({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods);
1556
1476
  }
1557
1477
 
1558
1478
  // define iterator
@@ -1675,7 +1595,7 @@ var DOMTokenListPrototype$1 = classList && classList.constructor && classList.co
1675
1595
 
1676
1596
  var domTokenListPrototype = DOMTokenListPrototype$1 === Object.prototype ? undefined : DOMTokenListPrototype$1;
1677
1597
 
1678
- var global$2 = global$d;
1598
+ var global$3 = global$d;
1679
1599
  var DOMIterables = domIterables;
1680
1600
  var DOMTokenListPrototype = domTokenListPrototype;
1681
1601
  var ArrayIteratorMethods = es_array_iterator;
@@ -1709,7 +1629,7 @@ var handlePrototype = function (CollectionPrototype, COLLECTION_NAME) {
1709
1629
  };
1710
1630
 
1711
1631
  for (var COLLECTION_NAME in DOMIterables) {
1712
- handlePrototype(global$2[COLLECTION_NAME] && global$2[COLLECTION_NAME].prototype, COLLECTION_NAME);
1632
+ handlePrototype(global$3[COLLECTION_NAME] && global$3[COLLECTION_NAME].prototype, COLLECTION_NAME);
1713
1633
  }
1714
1634
 
1715
1635
  handlePrototype(DOMTokenListPrototype, 'DOMTokenList');
@@ -1751,7 +1671,110 @@ function __awaiter(thisArg, _arguments, P, generator) {
1751
1671
  });
1752
1672
  }
1753
1673
 
1754
- const EXPERIENCE_TRAIT_PREFIX = 'nt_experiment_';
1674
+ var wellKnownSymbol$1 = wellKnownSymbol$8;
1675
+
1676
+ var TO_STRING_TAG$1 = wellKnownSymbol$1('toStringTag');
1677
+ var test = {};
1678
+
1679
+ test[TO_STRING_TAG$1] = 'z';
1680
+
1681
+ var toStringTagSupport = String(test) === '[object z]';
1682
+
1683
+ var TO_STRING_TAG_SUPPORT = toStringTagSupport;
1684
+ var isCallable$1 = isCallable$g;
1685
+ var classofRaw = classofRaw$1;
1686
+ var wellKnownSymbol = wellKnownSymbol$8;
1687
+
1688
+ var TO_STRING_TAG = wellKnownSymbol('toStringTag');
1689
+ var $Object = Object;
1690
+
1691
+ // ES3 wrong here
1692
+ var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) == 'Arguments';
1693
+
1694
+ // fallback for IE11 Script Access Denied error
1695
+ var tryGet = function (it, key) {
1696
+ try {
1697
+ return it[key];
1698
+ } catch (error) { /* empty */ }
1699
+ };
1700
+
1701
+ // getting tag from ES6+ `Object.prototype.toString`
1702
+ var classof$2 = TO_STRING_TAG_SUPPORT ? classofRaw : function (it) {
1703
+ var O, tag, result;
1704
+ return it === undefined ? 'Undefined' : it === null ? 'Null'
1705
+ // @@toStringTag case
1706
+ : typeof (tag = tryGet(O = $Object(it), TO_STRING_TAG)) == 'string' ? tag
1707
+ // builtinTag case
1708
+ : CORRECT_ARGUMENTS ? classofRaw(O)
1709
+ // ES3 arguments fallback
1710
+ : (result = classofRaw(O)) == 'Object' && isCallable$1(O.callee) ? 'Arguments' : result;
1711
+ };
1712
+
1713
+ var classof$1 = classof$2;
1714
+
1715
+ var $String = String;
1716
+
1717
+ var toString$1 = function (argument) {
1718
+ if (classof$1(argument) === 'Symbol') throw TypeError('Cannot convert a Symbol value to a string');
1719
+ return $String(argument);
1720
+ };
1721
+
1722
+ var $$1 = _export;
1723
+ var DESCRIPTORS = descriptors;
1724
+ var global$2 = global$d;
1725
+ var uncurryThis = functionUncurryThis;
1726
+ var hasOwn = hasOwnProperty_1;
1727
+ var isCallable = isCallable$g;
1728
+ var isPrototypeOf = objectIsPrototypeOf;
1729
+ var toString = toString$1;
1730
+ var defineProperty = objectDefineProperty.f;
1731
+ var copyConstructorProperties = copyConstructorProperties$2;
1732
+
1733
+ var NativeSymbol = global$2.Symbol;
1734
+ var SymbolPrototype = NativeSymbol && NativeSymbol.prototype;
1735
+
1736
+ if (DESCRIPTORS && isCallable(NativeSymbol) && (!('description' in SymbolPrototype) ||
1737
+ // Safari 12 bug
1738
+ NativeSymbol().description !== undefined
1739
+ )) {
1740
+ var EmptyStringDescriptionStore = {};
1741
+ // wrap Symbol constructor for correct work with undefined description
1742
+ var SymbolWrapper = function Symbol() {
1743
+ var description = arguments.length < 1 || arguments[0] === undefined ? undefined : toString(arguments[0]);
1744
+ var result = isPrototypeOf(SymbolPrototype, this)
1745
+ ? new NativeSymbol(description)
1746
+ // in Edge 13, String(Symbol(undefined)) === 'Symbol(undefined)'
1747
+ : description === undefined ? NativeSymbol() : NativeSymbol(description);
1748
+ if (description === '') EmptyStringDescriptionStore[result] = true;
1749
+ return result;
1750
+ };
1751
+
1752
+ copyConstructorProperties(SymbolWrapper, NativeSymbol);
1753
+ SymbolWrapper.prototype = SymbolPrototype;
1754
+ SymbolPrototype.constructor = SymbolWrapper;
1755
+
1756
+ var NATIVE_SYMBOL = String(NativeSymbol('test')) == 'Symbol(test)';
1757
+ var thisSymbolValue = uncurryThis(SymbolPrototype.valueOf);
1758
+ var symbolDescriptiveString = uncurryThis(SymbolPrototype.toString);
1759
+ var regexp = /^Symbol\((.*)\)[^)]+$/;
1760
+ var replace = uncurryThis(''.replace);
1761
+ var stringSlice = uncurryThis(''.slice);
1762
+
1763
+ defineProperty(SymbolPrototype, 'description', {
1764
+ configurable: true,
1765
+ get: function description() {
1766
+ var symbol = thisSymbolValue(this);
1767
+ if (hasOwn(EmptyStringDescriptionStore, symbol)) return '';
1768
+ var string = symbolDescriptiveString(symbol);
1769
+ var desc = NATIVE_SYMBOL ? stringSlice(string, 7, -1) : replace(string, regexp, '$1');
1770
+ return desc === '' ? undefined : desc;
1771
+ }
1772
+ });
1773
+
1774
+ $$1({ global: true, constructor: true, forced: true }, {
1775
+ Symbol: SymbolWrapper
1776
+ });
1777
+ }
1755
1778
 
1756
1779
  const useNinetailed = () => {
1757
1780
  const ninetailed = React.useContext(NinetailedContext);
@@ -1761,421 +1784,162 @@ const useNinetailed = () => {
1761
1784
  return ninetailed;
1762
1785
  };
1763
1786
 
1764
- const debounce = (fn, wait, options) => {
1765
- let debouncedArgs = [];
1766
- const debouncedFn = _debounce__default["default"](() => {
1767
- fn.call(undefined, debouncedArgs);
1768
- debouncedArgs = [];
1769
- }, wait, options);
1770
- return (...args) => {
1771
- debouncedArgs.push(values__default["default"](args));
1772
- debouncedFn();
1773
- };
1774
- };
1775
- const useProvideJoinExperiment = ({
1776
- experiments,
1777
- maximumActiveExperiments: _maximumActiveExperiments = 1
1787
+ const TrackExperience = ({
1788
+ children,
1789
+ experience,
1790
+ variant,
1791
+ profile
1778
1792
  }) => {
1793
+ const ninetailed = useNinetailed();
1779
1794
  const {
1780
- identify
1781
- } = useNinetailed();
1782
- const joinExperimentIdentify = debounce(args => {
1783
- const traits = args.slice(0, _maximumActiveExperiments).reduce((traits, [experimentJoinTraits]) => {
1784
- return Object.assign(Object.assign({}, experimentJoinTraits), traits);
1785
- }, {});
1786
- identify('', traits);
1795
+ ref,
1796
+ inView
1797
+ } = reactIntersectionObserver.useInView({
1798
+ triggerOnce: true
1787
1799
  });
1788
- return React.useCallback(data => __awaiter(void 0, void 0, void 0, function* () {
1789
- const {
1790
- experiment,
1791
- profile
1792
- } = data;
1793
- const isExperiment = experiment.type === 'nt_experiment';
1794
- if (!isExperiment) {
1795
- experience_jsShared.logger.warn(`The experience ${experiment.id}, which you tried to join, is not an experiment.`);
1796
- return;
1797
- }
1798
- const activeExperiments = experience_js.selectActiveExperiments(experiments, profile);
1799
- if (activeExperiments.length >= _maximumActiveExperiments) {
1800
- experience_jsShared.logger.warn(`The maximum number of active experiments (${_maximumActiveExperiments}) has been reached.`);
1801
- return;
1802
- }
1803
- if (activeExperiments.some(activeExperiment => activeExperiment.id === experiment.id)) {
1804
- experience_jsShared.logger.debug(`The user is already part of experiment ${experiment.id}. Won't join again.`);
1805
- return;
1806
- }
1807
- joinExperimentIdentify({
1808
- [`${EXPERIENCE_TRAIT_PREFIX}${experiment.id}`]: true
1809
- });
1810
- experience_jsShared.logger.debug(`Sent event to join experiment ${experiment.id}.`);
1811
- }), []);
1812
- };
1813
-
1814
- const ExperimentsProvider = ({
1815
- experiments,
1816
- maximumActiveExperiments: _maximumActiveExperiments = 1,
1817
- children
1818
- }) => {
1819
- const joinExperiment = useProvideJoinExperiment({
1820
- experiments,
1821
- maximumActiveExperiments: _maximumActiveExperiments
1822
- });
1823
- return jsxRuntime.jsx(ExperimentsContext.Provider, Object.assign({
1824
- value: {
1825
- experiments,
1826
- joinExperiment
1827
- }
1828
- }, {
1829
- children: children
1830
- }));
1831
- };
1832
-
1833
- const NinetailedProvider = ({
1834
- children,
1835
- clientId,
1836
- experiments: _experiments = [],
1837
- maximumActiveExperiments,
1838
- environment,
1839
- preview,
1840
- url,
1841
- profile,
1842
- locale,
1843
- requestTimeout,
1844
- plugins: _plugins = [],
1845
- onLog,
1846
- onError
1847
- }) => {
1848
- const ninetailed = React.useMemo(() => new experience_js.Ninetailed({
1849
- clientId,
1850
- environment,
1851
- preview
1852
- }, {
1853
- url,
1854
- plugins: _plugins,
1855
- profile,
1856
- locale,
1857
- requestTimeout,
1858
- onLog,
1859
- onError
1860
- }), []);
1861
- return jsxRuntime.jsx(NinetailedContext.Provider, Object.assign({
1862
- value: ninetailed
1863
- }, {
1864
- children: jsxRuntime.jsx(ExperimentsProvider, Object.assign({
1865
- experiments: _experiments,
1866
- maximumActiveExperiments: maximumActiveExperiments
1867
- }, {
1868
- children: children
1869
- }))
1870
- }));
1871
- };
1872
-
1873
- const useProfile = () => {
1874
- const ninetailed = useNinetailed();
1875
- const [profileState, setProfileState] = React.useState(ninetailed.profileState);
1876
- const profileStateRef = React.useRef({});
1877
- /**
1878
- * This effect compares the old and new profile state before updating it.
1879
- * We use a ref to avoid an infinite loop which can happen when an empty profile state was updated with no changes.
1880
- * This behaviour occurred as the validation handling on the error property was not set properly in the "CreateProfile" and "UpdateProfile" endpoint types.
1881
- * Furthermore, it was also observed, that it "only" occurred when the preview plugin was used in parallel.
1882
- */
1883
- React.useEffect(() => {
1884
- ninetailed.onProfileChange(profileState => {
1885
- if (isEqual__default["default"](profileState, profileStateRef.current)) {
1886
- experience_jsShared.logger.debug('Profile State Did Not Change', profileState);
1887
- return;
1888
- } else {
1889
- setProfileState(profileState);
1890
- profileStateRef.current = profileState;
1891
- experience_jsShared.logger.debug('Profile State Changed', profileState);
1892
- }
1893
- });
1894
- }, []);
1895
- /**
1896
- * Old implementation without profile state deep comparison
1897
- */
1898
- /*useEffect(() => {
1899
- return ninetailed.onProfileChange((profileState) => {
1900
- console.log('profileState', profileState);
1901
- setProfileState(profileState);
1902
- });
1903
- }, []);*/
1904
- return Object.assign(Object.assign({}, profileState), {
1905
- loading: profileState.status === 'loading'
1906
- });
1907
- };
1908
-
1909
- const usePersonalize = (baseline, variants, options = {
1910
- holdout: -1
1911
- }) => {
1912
- const profile = useProfile();
1913
- return experience_js.selectVariant(baseline, variants, profile, options);
1914
- };
1915
-
1916
- const TrackHasSeenComponent = ({
1917
- children,
1918
- variant,
1919
- audience,
1920
- isPersonalized
1921
- }) => {
1922
- const ninetailed = useNinetailed();
1923
- const {
1924
- ref,
1925
- inView
1926
- } = reactIntersectionObserver.useInView({
1927
- triggerOnce: true
1928
- });
1929
- React.useEffect(() => {
1930
- if (experience_jsShared.isBrowser() && inView) {
1931
- ninetailed.trackHasSeenComponent({
1932
- variant,
1933
- audience,
1934
- isPersonalized
1935
- });
1800
+ React.useEffect(() => {
1801
+ if (experience_jsShared.isBrowser() && inView) {
1802
+ const distribution = experience_js.selectDistribution({
1803
+ experience,
1804
+ profile
1805
+ });
1806
+ ninetailed.trackHasSeenExperience({
1807
+ experience: {
1808
+ id: experience.id,
1809
+ type: experience.type,
1810
+ name: experience.name || '',
1811
+ description: experience.description || ''
1812
+ },
1813
+ audience: experience.audience,
1814
+ selectedVariant: variant,
1815
+ selectedVariantIndex: distribution.index
1816
+ });
1936
1817
  }
1937
1818
  }, [inView]);
1938
1819
  return jsxRuntime.jsxs(jsxRuntime.Fragment, {
1939
1820
  children: [jsxRuntime.jsx("div", {
1940
- ref: ref
1821
+ ref: ref,
1822
+ id: "nt-experience-handle"
1941
1823
  }), children]
1942
1824
  });
1943
1825
  };
1944
1826
 
1945
- const Personalize = _a => {
1946
- var {
1947
- component: Component,
1948
- loadingComponent: LoadingComponent,
1949
- variants = [],
1950
- holdout = -1
1951
- } = _a,
1952
- baseline = __rest(_a, ["component", "loadingComponent", "variants", "holdout"]);
1953
- const {
1954
- loading,
1955
- variant,
1956
- isPersonalized,
1957
- audience
1958
- } = usePersonalize(baseline, variants, {
1959
- holdout
1960
- });
1961
- const hasVariants = variants.length > 0;
1962
- if (!hasVariants) {
1963
- return jsxRuntime.jsx(Component, Object.assign({}, baseline, {
1964
- ninetailed: {
1965
- isPersonalized,
1966
- audience
1967
- }
1968
- }));
1969
- }
1970
- if (loading) {
1971
- if (LoadingComponent) {
1972
- return jsxRuntime.jsx(LoadingComponent, {});
1973
- }
1974
- return jsxRuntime.jsx("div", Object.assign({
1975
- style: {
1976
- opacity: 0
1977
- }
1978
- }, {
1979
- children: jsxRuntime.jsx(Component, Object.assign({}, variant, {
1980
- ninetailed: {
1981
- isPersonalized,
1982
- audience
1983
- }
1984
- }))
1985
- }), "hide");
1986
- }
1987
- return jsxRuntime.jsx(TrackHasSeenComponent, Object.assign({
1988
- variant: variant,
1989
- audience: audience,
1990
- isPersonalized: isPersonalized
1991
- }, {
1992
- children: /*#__PURE__*/React.createElement(Component, Object.assign({}, variant, {
1993
- key: `${audience.id}-${variant.id}`,
1994
- ninetailed: {
1995
- isPersonalized,
1996
- audience
1997
- }
1998
- }))
1999
- }));
2000
- };
2001
-
2002
- const generateSelectors = id => {
2003
- return id.split('_').map((path, index, paths) => {
2004
- const dotPath = paths.slice(0, index).join('.');
2005
- const underScorePath = paths.slice(index).join('_');
2006
- return [dotPath, underScorePath].filter(path => path !== '').join('.');
2007
- });
2008
- };
2009
- const selectValueFromProfile = (profile, id) => {
2010
- const selectors = generateSelectors(id);
2011
- const matchingSelector = selectors.find(selector => get__default["default"](profile, selector));
2012
- if (!matchingSelector) {
2013
- return null;
2014
- }
2015
- return get__default["default"](profile, matchingSelector);
2016
- };
2017
- const MergeTag = ({
2018
- id
2019
- }) => {
2020
- const {
2021
- loading,
2022
- profile
2023
- } = useProfile();
2024
- if (loading || !profile) {
2025
- return null;
2026
- }
2027
- const value = selectValueFromProfile(profile, id);
2028
- // DON'T CHANGE
2029
- return jsxRuntime.jsx(jsxRuntime.Fragment, {
2030
- children: value
2031
- });
2032
- };
2033
-
2034
- var wellKnownSymbol$1 = wellKnownSymbol$8;
2035
-
2036
- var TO_STRING_TAG$1 = wellKnownSymbol$1('toStringTag');
2037
- var test = {};
2038
-
2039
- test[TO_STRING_TAG$1] = 'z';
2040
-
2041
- var toStringTagSupport = String(test) === '[object z]';
2042
-
2043
- var TO_STRING_TAG_SUPPORT = toStringTagSupport;
2044
- var isCallable$1 = isCallable$g;
2045
- var classofRaw = classofRaw$1;
2046
- var wellKnownSymbol = wellKnownSymbol$8;
2047
-
2048
- var TO_STRING_TAG = wellKnownSymbol('toStringTag');
2049
- var $Object = Object;
1827
+ var aCallable = aCallable$2;
1828
+ var toObject = toObject$4;
1829
+ var IndexedObject = indexedObject;
1830
+ var lengthOfArrayLike = lengthOfArrayLike$2;
2050
1831
 
2051
- // ES3 wrong here
2052
- var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) == 'Arguments';
1832
+ var $TypeError = TypeError;
2053
1833
 
2054
- // fallback for IE11 Script Access Denied error
2055
- var tryGet = function (it, key) {
2056
- try {
2057
- return it[key];
2058
- } catch (error) { /* empty */ }
1834
+ // `Array.prototype.{ reduce, reduceRight }` methods implementation
1835
+ var createMethod = function (IS_RIGHT) {
1836
+ return function (that, callbackfn, argumentsLength, memo) {
1837
+ aCallable(callbackfn);
1838
+ var O = toObject(that);
1839
+ var self = IndexedObject(O);
1840
+ var length = lengthOfArrayLike(O);
1841
+ var index = IS_RIGHT ? length - 1 : 0;
1842
+ var i = IS_RIGHT ? -1 : 1;
1843
+ if (argumentsLength < 2) while (true) {
1844
+ if (index in self) {
1845
+ memo = self[index];
1846
+ index += i;
1847
+ break;
1848
+ }
1849
+ index += i;
1850
+ if (IS_RIGHT ? index < 0 : length <= index) {
1851
+ throw $TypeError('Reduce of empty array with no initial value');
1852
+ }
1853
+ }
1854
+ for (;IS_RIGHT ? index >= 0 : length > index; index += i) if (index in self) {
1855
+ memo = callbackfn(memo, self[index], index, O);
1856
+ }
1857
+ return memo;
1858
+ };
2059
1859
  };
2060
1860
 
2061
- // getting tag from ES6+ `Object.prototype.toString`
2062
- var classof$1 = TO_STRING_TAG_SUPPORT ? classofRaw : function (it) {
2063
- var O, tag, result;
2064
- return it === undefined ? 'Undefined' : it === null ? 'Null'
2065
- // @@toStringTag case
2066
- : typeof (tag = tryGet(O = $Object(it), TO_STRING_TAG)) == 'string' ? tag
2067
- // builtinTag case
2068
- : CORRECT_ARGUMENTS ? classofRaw(O)
2069
- // ES3 arguments fallback
2070
- : (result = classofRaw(O)) == 'Object' && isCallable$1(O.callee) ? 'Arguments' : result;
1861
+ var arrayReduce = {
1862
+ // `Array.prototype.reduce` method
1863
+ // https://tc39.es/ecma262/#sec-array.prototype.reduce
1864
+ left: createMethod(false),
1865
+ // `Array.prototype.reduceRight` method
1866
+ // https://tc39.es/ecma262/#sec-array.prototype.reduceright
1867
+ right: createMethod(true)
2071
1868
  };
2072
1869
 
2073
- var classof = classof$1;
2074
-
2075
- var $String = String;
1870
+ var fails = fails$c;
2076
1871
 
2077
- var toString$1 = function (argument) {
2078
- if (classof(argument) === 'Symbol') throw TypeError('Cannot convert a Symbol value to a string');
2079
- return $String(argument);
1872
+ var arrayMethodIsStrict$1 = function (METHOD_NAME, argument) {
1873
+ var method = [][METHOD_NAME];
1874
+ return !!method && fails(function () {
1875
+ // eslint-disable-next-line no-useless-call -- required for testing
1876
+ method.call(null, argument || function () { return 1; }, 1);
1877
+ });
2080
1878
  };
2081
1879
 
2082
- var $ = _export;
2083
- var DESCRIPTORS = descriptors;
1880
+ var classof = classofRaw$1;
2084
1881
  var global$1 = global$d;
2085
- var uncurryThis = functionUncurryThis;
2086
- var hasOwn = hasOwnProperty_1;
2087
- var isCallable = isCallable$g;
2088
- var isPrototypeOf = objectIsPrototypeOf;
2089
- var toString = toString$1;
2090
- var defineProperty = objectDefineProperty.f;
2091
- var copyConstructorProperties = copyConstructorProperties$2;
2092
1882
 
2093
- var NativeSymbol = global$1.Symbol;
2094
- var SymbolPrototype = NativeSymbol && NativeSymbol.prototype;
1883
+ var engineIsNode = classof(global$1.process) == 'process';
2095
1884
 
2096
- if (DESCRIPTORS && isCallable(NativeSymbol) && (!('description' in SymbolPrototype) ||
2097
- // Safari 12 bug
2098
- NativeSymbol().description !== undefined
2099
- )) {
2100
- var EmptyStringDescriptionStore = {};
2101
- // wrap Symbol constructor for correct work with undefined description
2102
- var SymbolWrapper = function Symbol() {
2103
- var description = arguments.length < 1 || arguments[0] === undefined ? undefined : toString(arguments[0]);
2104
- var result = isPrototypeOf(SymbolPrototype, this)
2105
- ? new NativeSymbol(description)
2106
- // in Edge 13, String(Symbol(undefined)) === 'Symbol(undefined)'
2107
- : description === undefined ? NativeSymbol() : NativeSymbol(description);
2108
- if (description === '') EmptyStringDescriptionStore[result] = true;
2109
- return result;
2110
- };
2111
-
2112
- copyConstructorProperties(SymbolWrapper, NativeSymbol);
2113
- SymbolWrapper.prototype = SymbolPrototype;
2114
- SymbolPrototype.constructor = SymbolWrapper;
2115
-
2116
- var NATIVE_SYMBOL = String(NativeSymbol('test')) == 'Symbol(test)';
2117
- var thisSymbolValue = uncurryThis(SymbolPrototype.valueOf);
2118
- var symbolDescriptiveString = uncurryThis(SymbolPrototype.toString);
2119
- var regexp = /^Symbol\((.*)\)[^)]+$/;
2120
- var replace = uncurryThis(''.replace);
2121
- var stringSlice = uncurryThis(''.slice);
1885
+ var $ = _export;
1886
+ var $reduce = arrayReduce.left;
1887
+ var arrayMethodIsStrict = arrayMethodIsStrict$1;
1888
+ var CHROME_VERSION = engineV8Version;
1889
+ var IS_NODE = engineIsNode;
2122
1890
 
2123
- defineProperty(SymbolPrototype, 'description', {
2124
- configurable: true,
2125
- get: function description() {
2126
- var symbol = thisSymbolValue(this);
2127
- if (hasOwn(EmptyStringDescriptionStore, symbol)) return '';
2128
- var string = symbolDescriptiveString(symbol);
2129
- var desc = NATIVE_SYMBOL ? stringSlice(string, 7, -1) : replace(string, regexp, '$1');
2130
- return desc === '' ? undefined : desc;
2131
- }
2132
- });
1891
+ var STRICT_METHOD = arrayMethodIsStrict('reduce');
1892
+ // Chrome 80-82 has a critical bug
1893
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
1894
+ var CHROME_BUG = !IS_NODE && CHROME_VERSION > 79 && CHROME_VERSION < 83;
2133
1895
 
2134
- $({ global: true, constructor: true, forced: true }, {
2135
- Symbol: SymbolWrapper
2136
- });
2137
- }
1896
+ // `Array.prototype.reduce` method
1897
+ // https://tc39.es/ecma262/#sec-array.prototype.reduce
1898
+ $({ target: 'Array', proto: true, forced: !STRICT_METHOD || CHROME_BUG }, {
1899
+ reduce: function reduce(callbackfn /* , initialValue */) {
1900
+ var length = arguments.length;
1901
+ return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : undefined);
1902
+ }
1903
+ });
2138
1904
 
2139
- const TrackExperience = ({
2140
- children,
2141
- experience,
2142
- variant,
2143
- profile
2144
- }) => {
1905
+ const useProfile = () => {
2145
1906
  const ninetailed = useNinetailed();
2146
- const {
2147
- ref,
2148
- inView
2149
- } = reactIntersectionObserver.useInView({
2150
- triggerOnce: true
2151
- });
1907
+ const [profileState, setProfileState] = React.useState(ninetailed.profileState);
1908
+ const profileStateRef = React.useRef({});
1909
+ /**
1910
+ * This effect compares the old and new profile state before updating it.
1911
+ * We use a ref to avoid an infinite loop which can happen when an empty profile state was updated with no changes.
1912
+ * This behaviour occurred as the validation handling on the error property was not set properly in the "CreateProfile" and "UpdateProfile" endpoint types.
1913
+ * Furthermore, it was also observed, that it "only" occurred when the preview plugin was used in parallel.
1914
+ */
2152
1915
  React.useEffect(() => {
2153
- if (experience_jsShared.isBrowser() && inView) {
2154
- const distribution = experience_js.selectDistribution({
2155
- experience,
2156
- profile
2157
- });
2158
- ninetailed.trackHasSeenExperience({
2159
- experience: {
2160
- id: experience.id,
2161
- type: experience.type,
2162
- name: experience.name || '',
2163
- description: experience.description || ''
2164
- },
2165
- audience: experience.audience,
2166
- selectedVariant: variant,
2167
- selectedVariantIndex: distribution.index
2168
- });
2169
- }
2170
- }, [inView]);
2171
- return jsxRuntime.jsxs(jsxRuntime.Fragment, {
2172
- children: [jsxRuntime.jsx("div", {
2173
- ref: ref,
2174
- id: "nt-experience-handle"
2175
- }), children]
1916
+ ninetailed.onProfileChange(profileState => {
1917
+ if (isEqual__default["default"](profileState, profileStateRef.current)) {
1918
+ experience_jsShared.logger.debug('Profile State Did Not Change', profileState);
1919
+ return;
1920
+ } else {
1921
+ setProfileState(profileState);
1922
+ profileStateRef.current = profileState;
1923
+ experience_jsShared.logger.debug('Profile State Changed', profileState);
1924
+ }
1925
+ });
1926
+ }, []);
1927
+ /**
1928
+ * Old implementation without profile state deep comparison
1929
+ */
1930
+ /*useEffect(() => {
1931
+ return ninetailed.onProfileChange((profileState) => {
1932
+ console.log('profileState', profileState);
1933
+ setProfileState(profileState);
1934
+ });
1935
+ }, []);*/
1936
+ return Object.assign(Object.assign({}, profileState), {
1937
+ loading: profileState.status === 'loading'
2176
1938
  });
2177
1939
  };
2178
1940
 
1941
+ const ExperimentsContext = /*#__PURE__*/React.createContext(undefined);
1942
+
2179
1943
  const useExperimentsContext = () => {
2180
1944
  const context = React.useContext(ExperimentsContext);
2181
1945
  if (context === undefined) {
@@ -2563,6 +2327,242 @@ const ESRLoadingComponent = _a => {
2563
2327
  }));
2564
2328
  };
2565
2329
 
2330
+ const EXPERIENCE_TRAIT_PREFIX = 'nt_experiment_';
2331
+
2332
+ const debounce = (fn, wait, options) => {
2333
+ let debouncedArgs = [];
2334
+ const debouncedFn = _debounce__default["default"](() => {
2335
+ fn.call(undefined, debouncedArgs);
2336
+ debouncedArgs = [];
2337
+ }, wait, options);
2338
+ return (...args) => {
2339
+ debouncedArgs.push(values__default["default"](args));
2340
+ debouncedFn();
2341
+ };
2342
+ };
2343
+ const useProvideJoinExperiment = ({
2344
+ experiments,
2345
+ maximumActiveExperiments: _maximumActiveExperiments = 1
2346
+ }) => {
2347
+ const {
2348
+ identify
2349
+ } = useNinetailed();
2350
+ const joinExperimentIdentify = debounce(args => {
2351
+ const traits = args.slice(0, _maximumActiveExperiments).reduce((traits, [experimentJoinTraits]) => {
2352
+ return Object.assign(Object.assign({}, experimentJoinTraits), traits);
2353
+ }, {});
2354
+ identify('', traits);
2355
+ });
2356
+ return React.useCallback(data => __awaiter(void 0, void 0, void 0, function* () {
2357
+ const {
2358
+ experiment,
2359
+ profile
2360
+ } = data;
2361
+ const isExperiment = experiment.type === 'nt_experiment';
2362
+ if (!isExperiment) {
2363
+ experience_jsShared.logger.warn(`The experience ${experiment.id}, which you tried to join, is not an experiment.`);
2364
+ return;
2365
+ }
2366
+ const activeExperiments = experience_js.selectActiveExperiments(experiments, profile);
2367
+ if (activeExperiments.length >= _maximumActiveExperiments) {
2368
+ experience_jsShared.logger.warn(`The maximum number of active experiments (${_maximumActiveExperiments}) has been reached.`);
2369
+ return;
2370
+ }
2371
+ if (activeExperiments.some(activeExperiment => activeExperiment.id === experiment.id)) {
2372
+ experience_jsShared.logger.debug(`The user is already part of experiment ${experiment.id}. Won't join again.`);
2373
+ return;
2374
+ }
2375
+ joinExperimentIdentify({
2376
+ [`${EXPERIENCE_TRAIT_PREFIX}${experiment.id}`]: true
2377
+ });
2378
+ experience_jsShared.logger.debug(`Sent event to join experiment ${experiment.id}.`);
2379
+ }), []);
2380
+ };
2381
+
2382
+ const ExperimentsProvider = ({
2383
+ experiments,
2384
+ maximumActiveExperiments: _maximumActiveExperiments = 1,
2385
+ children
2386
+ }) => {
2387
+ const joinExperiment = useProvideJoinExperiment({
2388
+ experiments,
2389
+ maximumActiveExperiments: _maximumActiveExperiments
2390
+ });
2391
+ return jsxRuntime.jsx(ExperimentsContext.Provider, Object.assign({
2392
+ value: {
2393
+ experiments,
2394
+ joinExperiment
2395
+ }
2396
+ }, {
2397
+ children: children
2398
+ }));
2399
+ };
2400
+
2401
+ const NinetailedProvider = ({
2402
+ children,
2403
+ clientId,
2404
+ experiments: _experiments = [],
2405
+ maximumActiveExperiments,
2406
+ environment,
2407
+ preview,
2408
+ url,
2409
+ profile,
2410
+ locale,
2411
+ requestTimeout,
2412
+ plugins: _plugins = [],
2413
+ onLog,
2414
+ onError
2415
+ }) => {
2416
+ const ninetailed = React.useMemo(() => new experience_js.Ninetailed({
2417
+ clientId,
2418
+ environment,
2419
+ preview
2420
+ }, {
2421
+ url,
2422
+ plugins: _plugins,
2423
+ profile,
2424
+ locale,
2425
+ requestTimeout,
2426
+ onLog,
2427
+ onError
2428
+ }), []);
2429
+ return jsxRuntime.jsx(NinetailedContext.Provider, Object.assign({
2430
+ value: ninetailed
2431
+ }, {
2432
+ children: jsxRuntime.jsx(ExperimentsProvider, Object.assign({
2433
+ experiments: _experiments,
2434
+ maximumActiveExperiments: maximumActiveExperiments
2435
+ }, {
2436
+ children: children
2437
+ }))
2438
+ }));
2439
+ };
2440
+
2441
+ const usePersonalize = (baseline, variants, options = {
2442
+ holdout: -1
2443
+ }) => {
2444
+ const profile = useProfile();
2445
+ return experience_js.selectVariant(baseline, variants, profile, options);
2446
+ };
2447
+
2448
+ const TrackHasSeenComponent = ({
2449
+ children,
2450
+ variant,
2451
+ audience,
2452
+ isPersonalized
2453
+ }) => {
2454
+ const ninetailed = useNinetailed();
2455
+ const {
2456
+ ref,
2457
+ inView
2458
+ } = reactIntersectionObserver.useInView({
2459
+ triggerOnce: true
2460
+ });
2461
+ React.useEffect(() => {
2462
+ if (experience_jsShared.isBrowser() && inView) {
2463
+ ninetailed.trackHasSeenComponent({
2464
+ variant,
2465
+ audience,
2466
+ isPersonalized
2467
+ });
2468
+ }
2469
+ }, [inView]);
2470
+ return jsxRuntime.jsxs(jsxRuntime.Fragment, {
2471
+ children: [jsxRuntime.jsx("div", {
2472
+ ref: ref
2473
+ }), children]
2474
+ });
2475
+ };
2476
+
2477
+ const Personalize = _a => {
2478
+ var {
2479
+ component: Component,
2480
+ loadingComponent: LoadingComponent,
2481
+ variants = [],
2482
+ holdout = -1
2483
+ } = _a,
2484
+ baseline = __rest(_a, ["component", "loadingComponent", "variants", "holdout"]);
2485
+ const {
2486
+ loading,
2487
+ variant,
2488
+ isPersonalized,
2489
+ audience
2490
+ } = usePersonalize(baseline, variants, {
2491
+ holdout
2492
+ });
2493
+ const hasVariants = variants.length > 0;
2494
+ if (!hasVariants) {
2495
+ return jsxRuntime.jsx(Component, Object.assign({}, baseline, {
2496
+ ninetailed: {
2497
+ isPersonalized,
2498
+ audience
2499
+ }
2500
+ }));
2501
+ }
2502
+ if (loading) {
2503
+ if (LoadingComponent) {
2504
+ return jsxRuntime.jsx(LoadingComponent, {});
2505
+ }
2506
+ return jsxRuntime.jsx("div", Object.assign({
2507
+ style: {
2508
+ opacity: 0
2509
+ }
2510
+ }, {
2511
+ children: jsxRuntime.jsx(Component, Object.assign({}, variant, {
2512
+ ninetailed: {
2513
+ isPersonalized,
2514
+ audience
2515
+ }
2516
+ }))
2517
+ }), "hide");
2518
+ }
2519
+ return jsxRuntime.jsx(TrackHasSeenComponent, Object.assign({
2520
+ variant: variant,
2521
+ audience: audience,
2522
+ isPersonalized: isPersonalized
2523
+ }, {
2524
+ children: /*#__PURE__*/React.createElement(Component, Object.assign({}, variant, {
2525
+ key: `${audience.id}-${variant.id}`,
2526
+ ninetailed: {
2527
+ isPersonalized,
2528
+ audience
2529
+ }
2530
+ }))
2531
+ }));
2532
+ };
2533
+
2534
+ const generateSelectors = id => {
2535
+ return id.split('_').map((path, index, paths) => {
2536
+ const dotPath = paths.slice(0, index).join('.');
2537
+ const underScorePath = paths.slice(index).join('_');
2538
+ return [dotPath, underScorePath].filter(path => path !== '').join('.');
2539
+ });
2540
+ };
2541
+ const selectValueFromProfile = (profile, id) => {
2542
+ const selectors = generateSelectors(id);
2543
+ const matchingSelector = selectors.find(selector => get__default["default"](profile, selector));
2544
+ if (!matchingSelector) {
2545
+ return null;
2546
+ }
2547
+ return get__default["default"](profile, matchingSelector);
2548
+ };
2549
+ const MergeTag = ({
2550
+ id
2551
+ }) => {
2552
+ const {
2553
+ loading,
2554
+ profile
2555
+ } = useProfile();
2556
+ if (loading || !profile) {
2557
+ return null;
2558
+ }
2559
+ const value = selectValueFromProfile(profile, id);
2560
+ // DON'T CHANGE
2561
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {
2562
+ children: value
2563
+ });
2564
+ };
2565
+
2566
2566
  exports.DefaultExperienceLoadingComponent = DefaultExperienceLoadingComponent;
2567
2567
  exports.ESRLoadingComponent = ESRLoadingComponent;
2568
2568
  exports.ESRProvider = ESRProvider;