@ninetailed/experience.js-react 2.0.0-beta.9 → 2.0.2

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/index.esm.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import React, { createContext, useMemo, useContext, useState, useEffect, useCallback } from 'react';
2
- import { Ninetailed, selectVariant, selectHasExperienceVariants, selectActiveExperiments, selectExperience, selectExperienceVariant } from '@ninetailed/experience.js';
2
+ import { Ninetailed, selectVariant, selectDistribution, selectHasExperienceVariants, selectActiveExperiments, selectExperience, selectExperienceVariant } from '@ninetailed/experience.js';
3
3
  import { useInView } from 'react-intersection-observer';
4
4
  import { isBrowser } from '@ninetailed/experience.js-shared';
5
5
  import get$1 from 'lodash/get';
6
+ import has$1 from 'lodash/has';
6
7
 
7
8
  const NinetailedContext = /*#__PURE__*/createContext(undefined);
8
9
 
@@ -2333,6 +2334,37 @@ const MergeTag = ({
2333
2334
  return /*#__PURE__*/React.createElement(React.Fragment, null, value);
2334
2335
  };
2335
2336
 
2337
+ const TrackExperience = ({
2338
+ children,
2339
+ experience,
2340
+ variant,
2341
+ profile
2342
+ }) => {
2343
+ const ninetailed = useNinetailed();
2344
+ const {
2345
+ ref,
2346
+ inView
2347
+ } = useInView({
2348
+ triggerOnce: true
2349
+ });
2350
+ useEffect(() => {
2351
+ if (isBrowser() && inView) {
2352
+ const distribution = selectDistribution({
2353
+ experience,
2354
+ profile
2355
+ });
2356
+ ninetailed.trackExperience({
2357
+ experience,
2358
+ component: variant,
2359
+ variant: distribution.index
2360
+ });
2361
+ }
2362
+ }, [inView]);
2363
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
2364
+ ref: ref
2365
+ }), children);
2366
+ };
2367
+
2336
2368
  var global$2 = global$w;
2337
2369
  var aCallable = aCallable$2;
2338
2370
  var toObject = toObject$5;
@@ -2515,7 +2547,8 @@ const useJoinExperiment = ({
2515
2547
  }) => {
2516
2548
  const {
2517
2549
  identify
2518
- } = useNinetailed();
2550
+ } = useNinetailed(); // TODO this gets called twice
2551
+
2519
2552
  return useCallback(({
2520
2553
  experiment,
2521
2554
  profile
@@ -2523,18 +2556,61 @@ const useJoinExperiment = ({
2523
2556
  const activeExperiments = selectActiveExperiments(experiences, profile);
2524
2557
 
2525
2558
  if (!activeExperiments.length && experiment.type === 'nt_experiment') {
2526
- identify('', {
2559
+ identify(profile.id, {
2527
2560
  [`${EXPERIENCE_TRAIT_PREFIX}${experiment.id}`]: true
2528
2561
  });
2529
2562
  }
2530
2563
  }, [experiences]);
2531
2564
  };
2532
2565
 
2566
+ const DefaultExperienceLoadingComponent = _a => {
2567
+ var {
2568
+ component: Component,
2569
+ experiences,
2570
+ unhideAfterMs = 5000
2571
+ } = _a,
2572
+ baseline = __rest(_a, ["component", "experiences", "unhideAfterMs"]);
2573
+
2574
+ const [hidden, setHidden] = useState(true);
2575
+ useEffect(() => {
2576
+ const timer = setTimeout(() => {
2577
+ setHidden(false);
2578
+ }, unhideAfterMs);
2579
+ return () => {
2580
+ clearTimeout(timer);
2581
+ };
2582
+ }, []);
2583
+
2584
+ if (hidden) {
2585
+ return /*#__PURE__*/React.createElement("div", {
2586
+ key: "hide",
2587
+ style: {
2588
+ opacity: 0
2589
+ }
2590
+ }, /*#__PURE__*/React.createElement(Component, Object.assign({}, baseline, {
2591
+ ninetailed: {
2592
+ isPersonalized: false,
2593
+ audience: {
2594
+ id: 'baseline'
2595
+ }
2596
+ }
2597
+ })));
2598
+ }
2599
+
2600
+ return /*#__PURE__*/React.createElement(Component, Object.assign({}, baseline, {
2601
+ ninetailed: {
2602
+ isPersonalized: false,
2603
+ audience: {
2604
+ id: 'baseline'
2605
+ }
2606
+ }
2607
+ }));
2608
+ };
2533
2609
  const Experience = _a => {
2534
2610
  var {
2535
2611
  experiences,
2536
2612
  component: Component,
2537
- loadingComponent: LoadingComponent
2613
+ loadingComponent: LoadingComponent = DefaultExperienceLoadingComponent
2538
2614
  } = _a,
2539
2615
  baseline = __rest(_a, ["experiences", "component", "loadingComponent"]);
2540
2616
 
@@ -2567,74 +2643,112 @@ const Experience = _a => {
2567
2643
  }
2568
2644
 
2569
2645
  if (status === 'loading') {
2570
- if (LoadingComponent) {
2571
- return /*#__PURE__*/React.createElement(LoadingComponent, null);
2572
- }
2646
+ return /*#__PURE__*/React.createElement(LoadingComponent, Object.assign({}, baseline, {
2647
+ experiences: experiences,
2648
+ component: Component
2649
+ }));
2650
+ }
2573
2651
 
2574
- return /*#__PURE__*/React.createElement("div", {
2575
- key: "hide",
2576
- style: {
2577
- opacity: 0
2578
- }
2579
- }, /*#__PURE__*/React.createElement(Component, Object.assign({}, baseline, {
2652
+ if (!experience) {
2653
+ return /*#__PURE__*/React.createElement(Component, Object.assign({}, baseline, {
2654
+ key: baseline.id,
2580
2655
  ninetailed: {
2581
2656
  isPersonalized: false,
2582
2657
  audience: {
2583
2658
  id: 'baseline'
2584
2659
  }
2585
2660
  }
2586
- })));
2661
+ }));
2587
2662
  }
2588
2663
 
2589
- if (!experience || !variant) {
2590
- return /*#__PURE__*/React.createElement(TrackHasSeenComponent, {
2591
- variant: {
2592
- id: baseline.id,
2593
- audience: {
2594
- id: 'baseline'
2595
- },
2596
- hidden: false
2597
- },
2598
- audience: {
2599
- id: 'baseline'
2600
- },
2601
- isPersonalized: false
2664
+ if (!variant) {
2665
+ return /*#__PURE__*/React.createElement(TrackExperience, {
2666
+ experience: experience,
2667
+ variant: baseline,
2668
+ // the profile is definitely defined, otherwise there wouldn't be an experience selected
2669
+ profile: profile
2602
2670
  }, /*#__PURE__*/React.createElement(Component, Object.assign({}, baseline, {
2603
2671
  key: baseline.id,
2604
2672
  ninetailed: {
2605
2673
  isPersonalized: false,
2606
2674
  audience: {
2607
- id: 'baseline'
2675
+ id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'all visitors'
2608
2676
  }
2609
2677
  }
2610
2678
  })));
2611
2679
  }
2612
2680
 
2613
- return (
2614
- /*#__PURE__*/
2615
- // TODO this needs to be resolved when we move away from the old standard
2616
- React.createElement(TrackHasSeenComponent, {
2617
- variant: {
2618
- id: variant.id,
2619
- audience: {
2620
- id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'baseline'
2621
- },
2622
- hidden: variant.hidden || false
2623
- },
2681
+ return /*#__PURE__*/React.createElement(TrackExperience, {
2682
+ experience: experience,
2683
+ variant: variant,
2684
+ // the profile is definitely defined, otherwise there wouldn't be an experience selected
2685
+ profile: profile
2686
+ }, (variant === null || variant === void 0 ? void 0 : variant.hidden) ? null : /*#__PURE__*/React.createElement(Component, Object.assign({}, variant, {
2687
+ key: `${experience.id}-${variant.id}`,
2688
+ ninetailed: {
2689
+ isPersonalized,
2624
2690
  audience: {
2625
- id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'baseline'
2626
- },
2627
- isPersonalized: isPersonalized
2628
- }, (variant === null || variant === void 0 ? void 0 : variant.hidden) ? null : /*#__PURE__*/React.createElement(Component, Object.assign({}, variant, {
2629
- key: `${experience.id}-${variant.id}`,
2630
- ninetailed: {
2631
- isPersonalized,
2632
- audience: {
2633
- id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'baseline'
2634
- }
2691
+ id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'all visitors'
2635
2692
  }
2636
- })))
2637
- );
2693
+ }
2694
+ })));
2695
+ };
2696
+
2697
+ const ESRContext = /*#__PURE__*/React.createContext(undefined);
2698
+ const ESRProvider = ({
2699
+ experienceVariantsMap,
2700
+ children
2701
+ }) => {
2702
+ return /*#__PURE__*/React.createElement(ESRContext.Provider, {
2703
+ value: {
2704
+ experienceVariantsMap
2705
+ }
2706
+ }, children);
2707
+ };
2708
+ const useESR = () => {
2709
+ const context = React.useContext(ESRContext);
2710
+
2711
+ if (context === undefined) {
2712
+ throw new Error('The component using the the context must be a descendant of the ESRProvider');
2713
+ }
2714
+
2715
+ return {
2716
+ experienceVariantsMap: context.experienceVariantsMap
2717
+ };
2718
+ };
2719
+ const ESRLoadingComponent = _a => {
2720
+ var {
2721
+ experiences,
2722
+ component: Component
2723
+ } = _a,
2724
+ baseline = __rest(_a, ["experiences", "component"]);
2725
+
2726
+ const {
2727
+ experienceVariantsMap
2728
+ } = useESR();
2729
+ const experience = experiences.find(experience => has$1(experienceVariantsMap, experience.id));
2730
+
2731
+ if (!experience) {
2732
+ return /*#__PURE__*/React.createElement(Component, Object.assign({}, baseline));
2733
+ }
2734
+
2735
+ const component = experience.components.find(component => component.baseline.id === baseline.id);
2736
+
2737
+ if (!component) {
2738
+ return /*#__PURE__*/React.createElement(Component, Object.assign({}, baseline));
2739
+ }
2740
+
2741
+ if (experienceVariantsMap[experience.id] === 0) {
2742
+ return /*#__PURE__*/React.createElement(Component, Object.assign({}, baseline));
2743
+ }
2744
+
2745
+ const variant = component.variants[experienceVariantsMap[experience.id] - 1];
2746
+
2747
+ if (!variant) {
2748
+ return /*#__PURE__*/React.createElement(Component, Object.assign({}, baseline));
2749
+ }
2750
+
2751
+ return /*#__PURE__*/React.createElement(Component, Object.assign({}, variant));
2638
2752
  };
2639
2753
 
2640
- export { Experience, MergeTag, NinetailedProvider, Personalize, TrackHasSeenComponent, useNinetailed, usePersonalize, useProfile };
2754
+ export { DefaultExperienceLoadingComponent, ESRLoadingComponent, ESRProvider, Experience, MergeTag, NinetailedProvider, Personalize, TrackHasSeenComponent, useNinetailed, usePersonalize, useProfile };
package/index.umd.js CHANGED
@@ -1,13 +1,14 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('@ninetailed/experience.js'), require('react-intersection-observer'), require('@ninetailed/experience.js-shared'), require('lodash/get')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'react', '@ninetailed/experience.js', 'react-intersection-observer', '@ninetailed/experience.js-shared', 'lodash/get'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.React = {}, global.React, global.experience_js, global.reactIntersectionObserver, global.experience_jsShared, global.get$1));
5
- })(this, (function (exports, React, experience_js, reactIntersectionObserver, experience_jsShared, get$1) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('@ninetailed/experience.js'), require('react-intersection-observer'), require('@ninetailed/experience.js-shared'), require('lodash/get'), require('lodash/has')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'react', '@ninetailed/experience.js', 'react-intersection-observer', '@ninetailed/experience.js-shared', 'lodash/get', 'lodash/has'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.React = {}, global.React, global.experience_js, global.reactIntersectionObserver, global.experience_jsShared, global.get$1, global.has$1));
5
+ })(this, (function (exports, React, experience_js, reactIntersectionObserver, experience_jsShared, get$1, has$1) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
9
9
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
10
10
  var get__default = /*#__PURE__*/_interopDefaultLegacy(get$1);
11
+ var has__default = /*#__PURE__*/_interopDefaultLegacy(has$1);
11
12
 
12
13
  var NinetailedContext = /*#__PURE__*/React.createContext(undefined);
13
14
 
@@ -1883,6 +1884,37 @@
1883
1884
  return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, value);
1884
1885
  };
1885
1886
 
1887
+ var TrackExperience = function TrackExperience(_a) {
1888
+ var children = _a.children,
1889
+ experience = _a.experience,
1890
+ variant = _a.variant,
1891
+ profile = _a.profile;
1892
+ var ninetailed = useNinetailed();
1893
+
1894
+ var _b = reactIntersectionObserver.useInView({
1895
+ triggerOnce: true
1896
+ }),
1897
+ ref = _b.ref,
1898
+ inView = _b.inView;
1899
+
1900
+ React.useEffect(function () {
1901
+ if (experience_jsShared.isBrowser() && inView) {
1902
+ var distribution = experience_js.selectDistribution({
1903
+ experience: experience,
1904
+ profile: profile
1905
+ });
1906
+ ninetailed.trackExperience({
1907
+ experience: experience,
1908
+ component: variant,
1909
+ variant: distribution.index
1910
+ });
1911
+ }
1912
+ }, [inView]);
1913
+ return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("div", {
1914
+ ref: ref
1915
+ }), children);
1916
+ };
1917
+
1886
1918
  var global$2 = global$t;
1887
1919
  var aCallable = aCallable$2;
1888
1920
  var toObject = toObject$3;
@@ -2063,7 +2095,8 @@
2063
2095
 
2064
2096
  var useJoinExperiment = function useJoinExperiment(_a) {
2065
2097
  var experiences = _a.experiences;
2066
- var identify = useNinetailed().identify;
2098
+ var identify = useNinetailed().identify; // TODO this gets called twice
2099
+
2067
2100
  return React.useCallback(function (_a) {
2068
2101
  var _b;
2069
2102
 
@@ -2072,28 +2105,74 @@
2072
2105
  var activeExperiments = experience_js.selectActiveExperiments(experiences, profile);
2073
2106
 
2074
2107
  if (!activeExperiments.length && experiment.type === 'nt_experiment') {
2075
- identify('', (_b = {}, _b["".concat(EXPERIENCE_TRAIT_PREFIX).concat(experiment.id)] = true, _b));
2108
+ identify(profile.id, (_b = {}, _b["".concat(EXPERIENCE_TRAIT_PREFIX).concat(experiment.id)] = true, _b));
2076
2109
  }
2077
2110
  }, [experiences]);
2078
2111
  };
2079
2112
 
2113
+ var DefaultExperienceLoadingComponent = function DefaultExperienceLoadingComponent(_a) {
2114
+ var Component = _a.component;
2115
+ _a.experiences;
2116
+ var _b = _a.unhideAfterMs,
2117
+ unhideAfterMs = _b === void 0 ? 5000 : _b,
2118
+ baseline = __rest(_a, ["component", "experiences", "unhideAfterMs"]);
2119
+
2120
+ var _c = React.useState(true),
2121
+ hidden = _c[0],
2122
+ setHidden = _c[1];
2123
+
2124
+ React.useEffect(function () {
2125
+ var timer = setTimeout(function () {
2126
+ setHidden(false);
2127
+ }, unhideAfterMs);
2128
+ return function () {
2129
+ clearTimeout(timer);
2130
+ };
2131
+ }, []);
2132
+
2133
+ if (hidden) {
2134
+ return /*#__PURE__*/React__default["default"].createElement("div", {
2135
+ key: "hide",
2136
+ style: {
2137
+ opacity: 0
2138
+ }
2139
+ }, /*#__PURE__*/React__default["default"].createElement(Component, __assign({}, baseline, {
2140
+ ninetailed: {
2141
+ isPersonalized: false,
2142
+ audience: {
2143
+ id: 'baseline'
2144
+ }
2145
+ }
2146
+ })));
2147
+ }
2148
+
2149
+ return /*#__PURE__*/React__default["default"].createElement(Component, __assign({}, baseline, {
2150
+ ninetailed: {
2151
+ isPersonalized: false,
2152
+ audience: {
2153
+ id: 'baseline'
2154
+ }
2155
+ }
2156
+ }));
2157
+ };
2080
2158
  var Experience = function Experience(_a) {
2081
2159
  var experiences = _a.experiences,
2082
2160
  Component = _a.component,
2083
- LoadingComponent = _a.loadingComponent,
2161
+ _b = _a.loadingComponent,
2162
+ LoadingComponent = _b === void 0 ? DefaultExperienceLoadingComponent : _b,
2084
2163
  baseline = __rest(_a, ["experiences", "component", "loadingComponent"]);
2085
2164
 
2086
- var _b = useExperience({
2165
+ var _c = useExperience({
2087
2166
  baseline: baseline,
2088
2167
  experiences: experiences
2089
2168
  }),
2090
- status = _b.status,
2091
- hasVariants = _b.hasVariants,
2092
- experience = _b.experience,
2093
- variant = _b.variant,
2094
- audience = _b.audience,
2095
- isPersonalized = _b.isPersonalized,
2096
- profile = _b.profile;
2169
+ status = _c.status,
2170
+ hasVariants = _c.hasVariants,
2171
+ experience = _c.experience,
2172
+ variant = _c.variant,
2173
+ audience = _c.audience,
2174
+ isPersonalized = _c.isPersonalized,
2175
+ profile = _c.profile;
2097
2176
 
2098
2177
  var joinExperiment = useJoinExperiment({
2099
2178
  experiences: experiences
@@ -2112,76 +2191,116 @@
2112
2191
  }
2113
2192
 
2114
2193
  if (status === 'loading') {
2115
- if (LoadingComponent) {
2116
- return /*#__PURE__*/React__default["default"].createElement(LoadingComponent, null);
2117
- }
2194
+ return /*#__PURE__*/React__default["default"].createElement(LoadingComponent, __assign({}, baseline, {
2195
+ experiences: experiences,
2196
+ component: Component
2197
+ }));
2198
+ }
2118
2199
 
2119
- return /*#__PURE__*/React__default["default"].createElement("div", {
2120
- key: "hide",
2121
- style: {
2122
- opacity: 0
2123
- }
2124
- }, /*#__PURE__*/React__default["default"].createElement(Component, __assign({}, baseline, {
2200
+ if (!experience) {
2201
+ return /*#__PURE__*/React__default["default"].createElement(Component, __assign({}, baseline, {
2202
+ key: baseline.id,
2125
2203
  ninetailed: {
2126
2204
  isPersonalized: false,
2127
2205
  audience: {
2128
2206
  id: 'baseline'
2129
2207
  }
2130
2208
  }
2131
- })));
2209
+ }));
2132
2210
  }
2133
2211
 
2134
- if (!experience || !variant) {
2135
- return /*#__PURE__*/React__default["default"].createElement(TrackHasSeenComponent, {
2136
- variant: {
2137
- id: baseline.id,
2138
- audience: {
2139
- id: 'baseline'
2140
- },
2141
- hidden: false
2142
- },
2143
- audience: {
2144
- id: 'baseline'
2145
- },
2146
- isPersonalized: false
2212
+ if (!variant) {
2213
+ return /*#__PURE__*/React__default["default"].createElement(TrackExperience, {
2214
+ experience: experience,
2215
+ variant: baseline,
2216
+ // the profile is definitely defined, otherwise there wouldn't be an experience selected
2217
+ profile: profile
2147
2218
  }, /*#__PURE__*/React__default["default"].createElement(Component, __assign({}, baseline, {
2148
2219
  key: baseline.id,
2149
2220
  ninetailed: {
2150
2221
  isPersonalized: false,
2151
2222
  audience: {
2152
- id: 'baseline'
2223
+ id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'all visitors'
2153
2224
  }
2154
2225
  }
2155
2226
  })));
2156
2227
  }
2157
2228
 
2158
- return (
2159
- /*#__PURE__*/
2160
- // TODO this needs to be resolved when we move away from the old standard
2161
- React__default["default"].createElement(TrackHasSeenComponent, {
2162
- variant: {
2163
- id: variant.id,
2164
- audience: {
2165
- id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'baseline'
2166
- },
2167
- hidden: variant.hidden || false
2168
- },
2229
+ return /*#__PURE__*/React__default["default"].createElement(TrackExperience, {
2230
+ experience: experience,
2231
+ variant: variant,
2232
+ // the profile is definitely defined, otherwise there wouldn't be an experience selected
2233
+ profile: profile
2234
+ }, (variant === null || variant === void 0 ? void 0 : variant.hidden) ? null : /*#__PURE__*/React__default["default"].createElement(Component, __assign({}, variant, {
2235
+ key: "".concat(experience.id, "-").concat(variant.id),
2236
+ ninetailed: {
2237
+ isPersonalized: isPersonalized,
2169
2238
  audience: {
2170
- id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'baseline'
2171
- },
2172
- isPersonalized: isPersonalized
2173
- }, (variant === null || variant === void 0 ? void 0 : variant.hidden) ? null : /*#__PURE__*/React__default["default"].createElement(Component, __assign({}, variant, {
2174
- key: "".concat(experience.id, "-").concat(variant.id),
2175
- ninetailed: {
2176
- isPersonalized: isPersonalized,
2177
- audience: {
2178
- id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'baseline'
2179
- }
2239
+ id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'all visitors'
2180
2240
  }
2181
- })))
2182
- );
2241
+ }
2242
+ })));
2243
+ };
2244
+
2245
+ var ESRContext = /*#__PURE__*/React__default["default"].createContext(undefined);
2246
+ var ESRProvider = function ESRProvider(_a) {
2247
+ var experienceVariantsMap = _a.experienceVariantsMap,
2248
+ children = _a.children;
2249
+ return /*#__PURE__*/React__default["default"].createElement(ESRContext.Provider, {
2250
+ value: {
2251
+ experienceVariantsMap: experienceVariantsMap
2252
+ }
2253
+ }, children);
2254
+ };
2255
+ var useESR = function useESR() {
2256
+ var context = React__default["default"].useContext(ESRContext);
2257
+
2258
+ if (context === undefined) {
2259
+ throw new Error('The component using the the context must be a descendant of the ESRProvider');
2260
+ }
2261
+
2262
+ return {
2263
+ experienceVariantsMap: context.experienceVariantsMap
2264
+ };
2265
+ };
2266
+ var ESRLoadingComponent = function ESRLoadingComponent(_a) {
2267
+ var experiences = _a.experiences,
2268
+ Component = _a.component,
2269
+ baseline = __rest(_a, ["experiences", "component"]);
2270
+
2271
+ var experienceVariantsMap = useESR().experienceVariantsMap;
2272
+ var experience = experiences.find(function (experience) {
2273
+ return has__default["default"](experienceVariantsMap, experience.id);
2274
+ });
2275
+
2276
+ if (!experience) {
2277
+ return /*#__PURE__*/React__default["default"].createElement(Component, __assign({}, baseline));
2278
+ }
2279
+
2280
+ var component = experience.components.find(function (component) {
2281
+ return component.baseline.id === baseline.id;
2282
+ });
2283
+
2284
+ if (!component) {
2285
+ return /*#__PURE__*/React__default["default"].createElement(Component, __assign({}, baseline));
2286
+ }
2287
+
2288
+ if (experienceVariantsMap[experience.id] === 0) {
2289
+ return /*#__PURE__*/React__default["default"].createElement(Component, __assign({}, baseline));
2290
+ }
2291
+
2292
+ var variant = component.variants[experienceVariantsMap[experience.id] - 1];
2293
+
2294
+ if (!variant) {
2295
+ return /*#__PURE__*/React__default["default"].createElement(Component, __assign({}, baseline));
2296
+ }
2297
+
2298
+ return /*#__PURE__*/React__default["default"].createElement(Component, __assign({}, variant));
2183
2299
  };
2184
2300
 
2301
+ exports.DefaultExperienceLoadingComponent = DefaultExperienceLoadingComponent;
2302
+ exports.ESRLoadingComponent = ESRLoadingComponent;
2303
+ exports.ESRProvider = ESRProvider;
2185
2304
  exports.Experience = Experience;
2186
2305
  exports.MergeTag = MergeTag;
2187
2306
  exports.NinetailedProvider = NinetailedProvider;
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { ExperienceLoadingComponent } from './Experience';
3
+ declare type ESRContextValue = {
4
+ experienceVariantsMap: Record<string, number>;
5
+ };
6
+ export declare const ESRContext: React.Context<ESRContextValue | undefined>;
7
+ declare type ESRProviderProps = {
8
+ experienceVariantsMap: Record<string, number>;
9
+ };
10
+ export declare const ESRProvider: React.FC<ESRProviderProps>;
11
+ export declare const useESR: () => {
12
+ experienceVariantsMap: Record<string, number>;
13
+ };
14
+ export declare const ESRLoadingComponent: ExperienceLoadingComponent;
15
+ export {};
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Baseline, ExperienceConfiguration } from '@ninetailed/experience.js';
3
- declare type ExperienceComponent<P extends Baseline> = React.ComponentType<Omit<P, 'id'> & {
3
+ export declare type ExperienceComponent<P extends Baseline> = React.ComponentType<Omit<P, 'id'> & {
4
4
  ninetailed?: {
5
5
  isPersonalized: boolean;
6
6
  audience: {
@@ -8,11 +8,20 @@ declare type ExperienceComponent<P extends Baseline> = React.ComponentType<Omit<
8
8
  };
9
9
  };
10
10
  }>;
11
- declare type ExperienceProps<P extends Baseline> = P & {
11
+ export declare type ExperienceBaseProps<P extends Baseline = Baseline> = P & {
12
12
  experiences: ExperienceConfiguration[];
13
13
  component: ExperienceComponent<P> | React.ComponentType<P>;
14
- loadingComponent?: React.ComponentType;
15
14
  };
15
+ export declare type ExperienceLoadingComponent<P extends Baseline = Baseline> = React.ComponentType<ExperienceBaseProps<P>>;
16
+ export declare type ExperienceProps<P extends Baseline> = ExperienceBaseProps<P> & {
17
+ experiences: ExperienceConfiguration[];
18
+ component: ExperienceComponent<P> | React.ComponentType<P>;
19
+ loadingComponent?: ExperienceLoadingComponent<P>;
20
+ };
21
+ declare type DefaultExperienceLoadingComponentProps = ExperienceBaseProps & {
22
+ unhideAfterMs?: number;
23
+ };
24
+ export declare const DefaultExperienceLoadingComponent: React.FC<DefaultExperienceLoadingComponentProps>;
16
25
  export declare const Experience: <P extends {
17
26
  id: string;
18
27
  }>({ experiences, component: Component, loadingComponent: LoadingComponent, ...baseline }: ExperienceProps<P>) => JSX.Element;
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { Profile } from '@ninetailed/experience.js-shared';
3
+ import { ExperienceConfiguration } from '@ninetailed/experience.js';
4
+ declare type TrackExperienceProps = {
5
+ experience: ExperienceConfiguration;
6
+ variant: {
7
+ id: string;
8
+ };
9
+ profile: Profile;
10
+ };
11
+ export declare const TrackExperience: React.FC<React.PropsWithChildren<TrackExperienceProps>>;
12
+ export {};
@@ -1 +1,3 @@
1
- export { Experience } from './Experience';
1
+ export { Experience, DefaultExperienceLoadingComponent } from './Experience';
2
+ export type { ExperienceProps, ExperienceBaseProps, ExperienceComponent, ExperienceLoadingComponent } from './Experience';
3
+ export { ESRProvider, ESRLoadingComponent } from './ESRLoadingComponent';
@@ -1,5 +1,5 @@
1
- import { ExperienceConfiguration } from './types';
2
1
  import { Profile } from '@ninetailed/experience.js';
2
+ import { ExperienceConfiguration } from './types';
3
3
  declare type UseJoinExperimentArgs = {
4
4
  experiences: ExperienceConfiguration[];
5
5
  };
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export type { Profile, Variant } from '@ninetailed/experience.js-shared';
2
- export type { ExperienceConfiguration, ExperienceType, } from '@ninetailed/experience.js';
2
+ export type { ExperienceConfiguration, ExperienceType, EXPERIENCE_TRAIT_PREFIX, } from '@ninetailed/experience.js';
3
3
  export { NinetailedProvider } from './NinetailedProvider';
4
4
  export type { NinetailedProviderProps } from './NinetailedProvider';
5
5
  export { useNinetailed } from './useNinetailed';
@@ -9,4 +9,5 @@ export { Personalize } from './Personalize';
9
9
  export type { PersonalizedComponent } from './Personalize';
10
10
  export { MergeTag } from './MergeTag';
11
11
  export { TrackHasSeenComponent } from './TrackHasSeenComponent';
12
- export { Experience } from './Experience';
12
+ export { Experience, ESRProvider, ESRLoadingComponent, DefaultExperienceLoadingComponent } from './Experience';
13
+ export type { ExperienceProps, ExperienceBaseProps, ExperienceComponent, ExperienceLoadingComponent, } from './Experience';
package/package.json CHANGED
@@ -1,20 +1,21 @@
1
1
  {
2
2
  "name": "@ninetailed/experience.js-react",
3
- "version": "2.0.0-beta.9",
3
+ "version": "2.0.2",
4
4
  "peerDependencies": {
5
5
  "react": ">=16.8.0"
6
6
  },
7
7
  "dependencies": {
8
8
  "@analytics/google-analytics": "0.5.3",
9
9
  "react-visibility-sensor": "5.1.1",
10
- "@ninetailed/experience.js": "2.0.0-beta.9",
10
+ "lodash": "^4.17.21",
11
+ "@ninetailed/experience.js": "2.0.2",
11
12
  "analytics": "^0.8.0",
12
- "@ninetailed/experience.js-shared": "2.0.0-beta.9",
13
+ "@ninetailed/experience.js-shared": "2.0.2",
13
14
  "uuid": "^8.3.2",
14
15
  "ts-toolbelt": "^9.6.0",
15
16
  "locale-enum": "^1.1.1",
16
17
  "i18n-iso-countries": "^7.3.0",
17
- "lodash": "^4.17.21",
18
+ "loglevel": "^1.8.0",
18
19
  "murmurhash-js": "^1.0.0",
19
20
  "react-intersection-observer": "^8.33.1"
20
21
  },