@ninetailed/experience.js-react 6.2.0 → 6.3.0-beta.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/index.cjs +214 -345
- package/index.js +218 -346
- package/lib/Experience/index.d.ts +0 -3
- package/lib/NinetailedProvider.d.ts +4 -9
- package/lib/index.d.ts +1 -1
- package/package.json +3 -3
- package/lib/Experience/ExperimentsContext.d.ts +0 -9
- package/lib/Experience/ExperimentsProvider.d.ts +0 -8
- package/lib/Experience/useExperiementsContext.d.ts +0 -4
- package/lib/Experience/useExperiments.d.ts +0 -3
- package/lib/Experience/useJoinExperiment.d.ts +0 -1
- package/lib/Experience/useProvideJoinExperiment.d.ts +0 -13
package/index.cjs
CHANGED
|
@@ -5,10 +5,10 @@ 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 reactIs = require('react-is');
|
|
9
8
|
var experience_jsShared = require('@ninetailed/experience.js-shared');
|
|
10
9
|
var radash = require('radash');
|
|
11
10
|
var reactIntersectionObserver = require('react-intersection-observer');
|
|
11
|
+
var reactIs = require('react-is');
|
|
12
12
|
|
|
13
13
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
14
14
|
|
|
@@ -1099,6 +1099,57 @@ $$2({ target: 'Object', stat: true, arity: 2, forced: Object.assign !== assign }
|
|
|
1099
1099
|
|
|
1100
1100
|
const NinetailedContext = /*#__PURE__*/React.createContext(undefined);
|
|
1101
1101
|
|
|
1102
|
+
const NinetailedProvider = props => {
|
|
1103
|
+
const ninetailed = React.useMemo(() => {
|
|
1104
|
+
if ('ninetailed' in props) {
|
|
1105
|
+
return props.ninetailed;
|
|
1106
|
+
}
|
|
1107
|
+
const {
|
|
1108
|
+
clientId,
|
|
1109
|
+
environment,
|
|
1110
|
+
preview,
|
|
1111
|
+
url,
|
|
1112
|
+
profile,
|
|
1113
|
+
locale,
|
|
1114
|
+
requestTimeout,
|
|
1115
|
+
plugins = [],
|
|
1116
|
+
onLog,
|
|
1117
|
+
onError,
|
|
1118
|
+
componentViewTrackingThreshold
|
|
1119
|
+
} = props;
|
|
1120
|
+
return new experience_js.Ninetailed({
|
|
1121
|
+
clientId,
|
|
1122
|
+
environment,
|
|
1123
|
+
preview
|
|
1124
|
+
}, {
|
|
1125
|
+
url,
|
|
1126
|
+
plugins,
|
|
1127
|
+
profile,
|
|
1128
|
+
locale,
|
|
1129
|
+
requestTimeout,
|
|
1130
|
+
onLog,
|
|
1131
|
+
onError,
|
|
1132
|
+
componentViewTrackingThreshold
|
|
1133
|
+
});
|
|
1134
|
+
}, []);
|
|
1135
|
+
const {
|
|
1136
|
+
children
|
|
1137
|
+
} = props;
|
|
1138
|
+
return jsxRuntime.jsx(NinetailedContext.Provider, Object.assign({
|
|
1139
|
+
value: ninetailed
|
|
1140
|
+
}, {
|
|
1141
|
+
children: children
|
|
1142
|
+
}));
|
|
1143
|
+
};
|
|
1144
|
+
|
|
1145
|
+
const useNinetailed = () => {
|
|
1146
|
+
const ninetailed = React.useContext(NinetailedContext);
|
|
1147
|
+
if (ninetailed === undefined) {
|
|
1148
|
+
throw new Error('The component using the the context must be a descendant of the NinetailedProvider');
|
|
1149
|
+
}
|
|
1150
|
+
return ninetailed;
|
|
1151
|
+
};
|
|
1152
|
+
|
|
1102
1153
|
var objectDefineProperties = {};
|
|
1103
1154
|
|
|
1104
1155
|
var DESCRIPTORS$1 = descriptors;
|
|
@@ -1626,6 +1677,49 @@ for (var COLLECTION_NAME in DOMIterables) {
|
|
|
1626
1677
|
|
|
1627
1678
|
handlePrototype(DOMTokenListPrototype, 'DOMTokenList');
|
|
1628
1679
|
|
|
1680
|
+
const useProfile = () => {
|
|
1681
|
+
const ninetailed = useNinetailed();
|
|
1682
|
+
const [profileState, setProfileState] = React.useState(ninetailed.profileState);
|
|
1683
|
+
const profileStateRef = React.useRef({});
|
|
1684
|
+
/**
|
|
1685
|
+
* This effect compares the old and new profile state before updating it.
|
|
1686
|
+
* We use a ref to avoid an infinite loop which can happen when an empty profile state was updated with no changes.
|
|
1687
|
+
* This behaviour occurred as the validation handling on the error property was not set properly in the "CreateProfile" and "UpdateProfile" endpoint types.
|
|
1688
|
+
* Furthermore, it was also observed, that it "only" occurred when the preview plugin was used in parallel.
|
|
1689
|
+
*/
|
|
1690
|
+
React.useEffect(() => {
|
|
1691
|
+
ninetailed.onProfileChange(profileState => {
|
|
1692
|
+
if (radash.isEqual(profileState, profileStateRef.current)) {
|
|
1693
|
+
experience_jsShared.logger.debug('Profile State Did Not Change', profileState);
|
|
1694
|
+
return;
|
|
1695
|
+
} else {
|
|
1696
|
+
setProfileState(profileState);
|
|
1697
|
+
profileStateRef.current = profileState;
|
|
1698
|
+
experience_jsShared.logger.debug('Profile State Changed', profileState);
|
|
1699
|
+
}
|
|
1700
|
+
});
|
|
1701
|
+
}, []);
|
|
1702
|
+
/**
|
|
1703
|
+
* Old implementation without profile state deep comparison
|
|
1704
|
+
*/
|
|
1705
|
+
/*useEffect(() => {
|
|
1706
|
+
return ninetailed.onProfileChange((profileState) => {
|
|
1707
|
+
console.log('profileState', profileState);
|
|
1708
|
+
setProfileState(profileState);
|
|
1709
|
+
});
|
|
1710
|
+
}, []);*/
|
|
1711
|
+
return Object.assign(Object.assign({}, profileState), {
|
|
1712
|
+
loading: profileState.status === 'loading'
|
|
1713
|
+
});
|
|
1714
|
+
};
|
|
1715
|
+
|
|
1716
|
+
const usePersonalize = (baseline, variants, options = {
|
|
1717
|
+
holdout: -1
|
|
1718
|
+
}) => {
|
|
1719
|
+
const profile = useProfile();
|
|
1720
|
+
return experience_js.selectVariant(baseline, variants, profile, options);
|
|
1721
|
+
};
|
|
1722
|
+
|
|
1629
1723
|
/******************************************************************************
|
|
1630
1724
|
Copyright (c) Microsoft Corporation.
|
|
1631
1725
|
|
|
@@ -1651,18 +1745,126 @@ function __rest(s, e) {
|
|
|
1651
1745
|
t[p[i]] = s[p[i]];
|
|
1652
1746
|
}
|
|
1653
1747
|
return t;
|
|
1654
|
-
}
|
|
1655
|
-
|
|
1656
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
1657
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
1658
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
1659
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
1660
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
1661
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
1662
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1663
|
-
});
|
|
1664
1748
|
}
|
|
1665
1749
|
|
|
1750
|
+
const TrackHasSeenComponent = ({
|
|
1751
|
+
children,
|
|
1752
|
+
variant,
|
|
1753
|
+
audience,
|
|
1754
|
+
isPersonalized
|
|
1755
|
+
}) => {
|
|
1756
|
+
const ninetailed = useNinetailed();
|
|
1757
|
+
const {
|
|
1758
|
+
ref,
|
|
1759
|
+
inView
|
|
1760
|
+
} = reactIntersectionObserver.useInView({
|
|
1761
|
+
triggerOnce: true
|
|
1762
|
+
});
|
|
1763
|
+
React.useEffect(() => {
|
|
1764
|
+
if (experience_jsShared.isBrowser() && inView) {
|
|
1765
|
+
ninetailed.trackHasSeenComponent({
|
|
1766
|
+
variant,
|
|
1767
|
+
audience,
|
|
1768
|
+
isPersonalized
|
|
1769
|
+
});
|
|
1770
|
+
}
|
|
1771
|
+
}, [inView]);
|
|
1772
|
+
return jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
1773
|
+
children: [jsxRuntime.jsx("div", {
|
|
1774
|
+
ref: ref
|
|
1775
|
+
}), children]
|
|
1776
|
+
});
|
|
1777
|
+
};
|
|
1778
|
+
|
|
1779
|
+
const Personalize = _a => {
|
|
1780
|
+
var {
|
|
1781
|
+
component: Component,
|
|
1782
|
+
loadingComponent: LoadingComponent,
|
|
1783
|
+
variants = [],
|
|
1784
|
+
holdout = -1
|
|
1785
|
+
} = _a,
|
|
1786
|
+
baseline = __rest(_a, ["component", "loadingComponent", "variants", "holdout"]);
|
|
1787
|
+
const {
|
|
1788
|
+
loading,
|
|
1789
|
+
variant,
|
|
1790
|
+
isPersonalized,
|
|
1791
|
+
audience
|
|
1792
|
+
} = usePersonalize(baseline, variants, {
|
|
1793
|
+
holdout
|
|
1794
|
+
});
|
|
1795
|
+
const hasVariants = variants.length > 0;
|
|
1796
|
+
if (!hasVariants) {
|
|
1797
|
+
return jsxRuntime.jsx(Component, Object.assign({}, baseline, {
|
|
1798
|
+
ninetailed: {
|
|
1799
|
+
isPersonalized,
|
|
1800
|
+
audience
|
|
1801
|
+
}
|
|
1802
|
+
}));
|
|
1803
|
+
}
|
|
1804
|
+
if (loading) {
|
|
1805
|
+
if (LoadingComponent) {
|
|
1806
|
+
return jsxRuntime.jsx(LoadingComponent, {});
|
|
1807
|
+
}
|
|
1808
|
+
return jsxRuntime.jsx("div", Object.assign({
|
|
1809
|
+
style: {
|
|
1810
|
+
opacity: 0
|
|
1811
|
+
}
|
|
1812
|
+
}, {
|
|
1813
|
+
children: jsxRuntime.jsx(Component, Object.assign({}, variant, {
|
|
1814
|
+
ninetailed: {
|
|
1815
|
+
isPersonalized,
|
|
1816
|
+
audience
|
|
1817
|
+
}
|
|
1818
|
+
}))
|
|
1819
|
+
}), "hide");
|
|
1820
|
+
}
|
|
1821
|
+
return jsxRuntime.jsx(TrackHasSeenComponent, Object.assign({
|
|
1822
|
+
variant: variant,
|
|
1823
|
+
audience: audience,
|
|
1824
|
+
isPersonalized: isPersonalized
|
|
1825
|
+
}, {
|
|
1826
|
+
children: /*#__PURE__*/React.createElement(Component, Object.assign({}, variant, {
|
|
1827
|
+
key: `${audience.id}-${variant.id}`,
|
|
1828
|
+
ninetailed: {
|
|
1829
|
+
isPersonalized,
|
|
1830
|
+
audience
|
|
1831
|
+
}
|
|
1832
|
+
}))
|
|
1833
|
+
}));
|
|
1834
|
+
};
|
|
1835
|
+
|
|
1836
|
+
const generateSelectors = id => {
|
|
1837
|
+
return id.split('_').map((path, index, paths) => {
|
|
1838
|
+
const dotPath = paths.slice(0, index).join('.');
|
|
1839
|
+
const underScorePath = paths.slice(index).join('_');
|
|
1840
|
+
return [dotPath, underScorePath].filter(path => path !== '').join('.');
|
|
1841
|
+
});
|
|
1842
|
+
};
|
|
1843
|
+
const selectValueFromProfile = (profile, id) => {
|
|
1844
|
+
const selectors = generateSelectors(id);
|
|
1845
|
+
const matchingSelector = selectors.find(selector => radash.get(profile, selector));
|
|
1846
|
+
if (!matchingSelector) {
|
|
1847
|
+
return null;
|
|
1848
|
+
}
|
|
1849
|
+
return radash.get(profile, matchingSelector);
|
|
1850
|
+
};
|
|
1851
|
+
const MergeTag = ({
|
|
1852
|
+
id
|
|
1853
|
+
}) => {
|
|
1854
|
+
const {
|
|
1855
|
+
loading,
|
|
1856
|
+
profile
|
|
1857
|
+
} = useProfile();
|
|
1858
|
+
if (loading || !profile) {
|
|
1859
|
+
return null;
|
|
1860
|
+
}
|
|
1861
|
+
const value = selectValueFromProfile(profile, id);
|
|
1862
|
+
// DON'T CHANGE
|
|
1863
|
+
return jsxRuntime.jsx(jsxRuntime.Fragment, {
|
|
1864
|
+
children: value
|
|
1865
|
+
});
|
|
1866
|
+
};
|
|
1867
|
+
|
|
1666
1868
|
var aCallable = aCallable$2;
|
|
1667
1869
|
var toObject = toObject$4;
|
|
1668
1870
|
var IndexedObject = indexedObject;
|
|
@@ -1741,67 +1943,6 @@ $({ target: 'Array', proto: true, forced: !STRICT_METHOD || CHROME_BUG }, {
|
|
|
1741
1943
|
}
|
|
1742
1944
|
});
|
|
1743
1945
|
|
|
1744
|
-
const useNinetailed = () => {
|
|
1745
|
-
const ninetailed = React.useContext(NinetailedContext);
|
|
1746
|
-
if (ninetailed === undefined) {
|
|
1747
|
-
throw new Error('The component using the the context must be a descendant of the NinetailedProvider');
|
|
1748
|
-
}
|
|
1749
|
-
return ninetailed;
|
|
1750
|
-
};
|
|
1751
|
-
|
|
1752
|
-
const useProfile = () => {
|
|
1753
|
-
const ninetailed = useNinetailed();
|
|
1754
|
-
const [profileState, setProfileState] = React.useState(ninetailed.profileState);
|
|
1755
|
-
const profileStateRef = React.useRef({});
|
|
1756
|
-
/**
|
|
1757
|
-
* This effect compares the old and new profile state before updating it.
|
|
1758
|
-
* We use a ref to avoid an infinite loop which can happen when an empty profile state was updated with no changes.
|
|
1759
|
-
* This behaviour occurred as the validation handling on the error property was not set properly in the "CreateProfile" and "UpdateProfile" endpoint types.
|
|
1760
|
-
* Furthermore, it was also observed, that it "only" occurred when the preview plugin was used in parallel.
|
|
1761
|
-
*/
|
|
1762
|
-
React.useEffect(() => {
|
|
1763
|
-
ninetailed.onProfileChange(profileState => {
|
|
1764
|
-
if (radash.isEqual(profileState, profileStateRef.current)) {
|
|
1765
|
-
experience_jsShared.logger.debug('Profile State Did Not Change', profileState);
|
|
1766
|
-
return;
|
|
1767
|
-
} else {
|
|
1768
|
-
setProfileState(profileState);
|
|
1769
|
-
profileStateRef.current = profileState;
|
|
1770
|
-
experience_jsShared.logger.debug('Profile State Changed', profileState);
|
|
1771
|
-
}
|
|
1772
|
-
});
|
|
1773
|
-
}, []);
|
|
1774
|
-
/**
|
|
1775
|
-
* Old implementation without profile state deep comparison
|
|
1776
|
-
*/
|
|
1777
|
-
/*useEffect(() => {
|
|
1778
|
-
return ninetailed.onProfileChange((profileState) => {
|
|
1779
|
-
console.log('profileState', profileState);
|
|
1780
|
-
setProfileState(profileState);
|
|
1781
|
-
});
|
|
1782
|
-
}, []);*/
|
|
1783
|
-
return Object.assign(Object.assign({}, profileState), {
|
|
1784
|
-
loading: profileState.status === 'loading'
|
|
1785
|
-
});
|
|
1786
|
-
};
|
|
1787
|
-
|
|
1788
|
-
const ExperimentsContext = /*#__PURE__*/React.createContext(undefined);
|
|
1789
|
-
|
|
1790
|
-
const useExperimentsContext = () => {
|
|
1791
|
-
const context = React.useContext(ExperimentsContext);
|
|
1792
|
-
if (context === undefined) {
|
|
1793
|
-
throw new Error('The component using the the context must be a descendant of the ExperimentsProvider');
|
|
1794
|
-
}
|
|
1795
|
-
return context;
|
|
1796
|
-
};
|
|
1797
|
-
|
|
1798
|
-
const useExperiments = () => {
|
|
1799
|
-
const context = useExperimentsContext();
|
|
1800
|
-
return {
|
|
1801
|
-
experiments: context.experiments
|
|
1802
|
-
};
|
|
1803
|
-
};
|
|
1804
|
-
|
|
1805
1946
|
const useExperienceSelectionMiddleware = ({
|
|
1806
1947
|
experiences,
|
|
1807
1948
|
baseline,
|
|
@@ -1836,9 +1977,6 @@ const useExperience = ({
|
|
|
1836
1977
|
experiences
|
|
1837
1978
|
}) => {
|
|
1838
1979
|
const profileState = useProfile();
|
|
1839
|
-
const {
|
|
1840
|
-
experiments
|
|
1841
|
-
} = useExperiments();
|
|
1842
1980
|
const hasVariants = experiences.map(experience => experience_js.selectHasExperienceVariants(experience, baseline)).reduce((acc, curr) => acc || curr, false);
|
|
1843
1981
|
const {
|
|
1844
1982
|
status,
|
|
@@ -1901,10 +2039,8 @@ const useExperience = ({
|
|
|
1901
2039
|
// @ts-ignore
|
|
1902
2040
|
return overrideResult(emptyReturn);
|
|
1903
2041
|
}
|
|
1904
|
-
const activeExperiments = experience_js.selectActiveExperiments(experiments, profile);
|
|
1905
2042
|
const experience = experience_js.selectExperience({
|
|
1906
2043
|
experiences,
|
|
1907
|
-
activeExperiments,
|
|
1908
2044
|
profile
|
|
1909
2045
|
});
|
|
1910
2046
|
if (!experience) {
|
|
@@ -1935,11 +2071,6 @@ const useExperience = ({
|
|
|
1935
2071
|
}));
|
|
1936
2072
|
};
|
|
1937
2073
|
|
|
1938
|
-
const useJoinExperiment = () => {
|
|
1939
|
-
const context = useExperimentsContext();
|
|
1940
|
-
return context.joinExperiment;
|
|
1941
|
-
};
|
|
1942
|
-
|
|
1943
2074
|
const ComponentMarker = /*#__PURE__*/React.forwardRef((_, ref) => {
|
|
1944
2075
|
const {
|
|
1945
2076
|
logger
|
|
@@ -2035,26 +2166,15 @@ const Experience = _a => {
|
|
|
2035
2166
|
variant,
|
|
2036
2167
|
variantIndex,
|
|
2037
2168
|
audience,
|
|
2038
|
-
isPersonalized
|
|
2039
|
-
profile
|
|
2169
|
+
isPersonalized
|
|
2040
2170
|
} = useExperience({
|
|
2041
2171
|
baseline,
|
|
2042
2172
|
experiences
|
|
2043
2173
|
});
|
|
2044
|
-
const joinExperiment = useJoinExperiment();
|
|
2045
2174
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2046
2175
|
// @ts-ignore
|
|
2047
2176
|
const isComponentForwardRef = reactIs.isForwardRef(jsxRuntime.jsx(Component, {}));
|
|
2048
2177
|
const componentRef = React.useRef(null);
|
|
2049
|
-
React.useEffect(() => {
|
|
2050
|
-
if (status === 'success' && experience && profile) {
|
|
2051
|
-
joinExperiment({
|
|
2052
|
-
experiences,
|
|
2053
|
-
experiment: experience,
|
|
2054
|
-
profile
|
|
2055
|
-
});
|
|
2056
|
-
}
|
|
2057
|
-
}, [status, experience, profile]);
|
|
2058
2178
|
React.useEffect(() => {
|
|
2059
2179
|
const componentElement = componentRef.current;
|
|
2060
2180
|
if (componentElement) {
|
|
@@ -2199,266 +2319,15 @@ const ESRLoadingComponent = _a => {
|
|
|
2199
2319
|
}));
|
|
2200
2320
|
};
|
|
2201
2321
|
|
|
2202
|
-
const EXPERIENCE_TRAIT_PREFIX = 'nt_experiment_';
|
|
2203
|
-
|
|
2204
|
-
const debounce = (fn, wait) => {
|
|
2205
|
-
let debouncedArgs = [];
|
|
2206
|
-
const debouncedFn = radash.debounce({
|
|
2207
|
-
delay: wait !== null && wait !== void 0 ? wait : 0
|
|
2208
|
-
}, () => {
|
|
2209
|
-
fn.call(undefined, debouncedArgs);
|
|
2210
|
-
debouncedArgs = [];
|
|
2211
|
-
});
|
|
2212
|
-
return (...args) => {
|
|
2213
|
-
debouncedArgs.push(args);
|
|
2214
|
-
debouncedFn();
|
|
2215
|
-
};
|
|
2216
|
-
};
|
|
2217
|
-
const useProvideJoinExperiment = ({
|
|
2218
|
-
experiments,
|
|
2219
|
-
maximumActiveExperiments: _maximumActiveExperiments = 1
|
|
2220
|
-
}) => {
|
|
2221
|
-
const {
|
|
2222
|
-
identify
|
|
2223
|
-
} = useNinetailed();
|
|
2224
|
-
const joinExperimentIdentify = debounce(args => {
|
|
2225
|
-
const traits = args.slice(0, _maximumActiveExperiments).reduce((traits, [experimentJoinTraits]) => {
|
|
2226
|
-
return Object.assign(Object.assign({}, experimentJoinTraits), traits);
|
|
2227
|
-
}, {});
|
|
2228
|
-
identify('', traits);
|
|
2229
|
-
});
|
|
2230
|
-
return React.useCallback(data => __awaiter(void 0, void 0, void 0, function* () {
|
|
2231
|
-
const {
|
|
2232
|
-
experiment,
|
|
2233
|
-
profile
|
|
2234
|
-
} = data;
|
|
2235
|
-
const isExperiment = experiment.type === 'nt_experiment';
|
|
2236
|
-
if (!isExperiment) {
|
|
2237
|
-
experience_jsShared.logger.warn(`The experience ${experiment.id}, which you tried to join, is not an experiment.`);
|
|
2238
|
-
return;
|
|
2239
|
-
}
|
|
2240
|
-
const activeExperiments = experience_js.selectActiveExperiments(experiments, profile);
|
|
2241
|
-
if (activeExperiments.length >= _maximumActiveExperiments) {
|
|
2242
|
-
experience_jsShared.logger.warn(`The maximum number of active experiments (${_maximumActiveExperiments}) has been reached.`);
|
|
2243
|
-
return;
|
|
2244
|
-
}
|
|
2245
|
-
if (activeExperiments.some(activeExperiment => activeExperiment.id === experiment.id)) {
|
|
2246
|
-
experience_jsShared.logger.debug(`The user is already part of experiment ${experiment.id}. Won't join again.`);
|
|
2247
|
-
return;
|
|
2248
|
-
}
|
|
2249
|
-
joinExperimentIdentify({
|
|
2250
|
-
[`${EXPERIENCE_TRAIT_PREFIX}${experiment.id}`]: true
|
|
2251
|
-
});
|
|
2252
|
-
experience_jsShared.logger.debug(`Sent event to join experiment ${experiment.id}.`);
|
|
2253
|
-
}), []);
|
|
2254
|
-
};
|
|
2255
|
-
|
|
2256
|
-
const ExperimentsProvider = ({
|
|
2257
|
-
experiments,
|
|
2258
|
-
maximumActiveExperiments: _maximumActiveExperiments = 1,
|
|
2259
|
-
children
|
|
2260
|
-
}) => {
|
|
2261
|
-
const joinExperiment = useProvideJoinExperiment({
|
|
2262
|
-
experiments,
|
|
2263
|
-
maximumActiveExperiments: _maximumActiveExperiments
|
|
2264
|
-
});
|
|
2265
|
-
return jsxRuntime.jsx(ExperimentsContext.Provider, Object.assign({
|
|
2266
|
-
value: {
|
|
2267
|
-
experiments,
|
|
2268
|
-
joinExperiment
|
|
2269
|
-
}
|
|
2270
|
-
}, {
|
|
2271
|
-
children: children
|
|
2272
|
-
}));
|
|
2273
|
-
};
|
|
2274
|
-
|
|
2275
|
-
const NinetailedProvider = props => {
|
|
2276
|
-
const ninetailed = React.useMemo(() => {
|
|
2277
|
-
if ('ninetailed' in props) {
|
|
2278
|
-
return props.ninetailed;
|
|
2279
|
-
}
|
|
2280
|
-
const {
|
|
2281
|
-
clientId,
|
|
2282
|
-
environment,
|
|
2283
|
-
preview,
|
|
2284
|
-
url,
|
|
2285
|
-
profile,
|
|
2286
|
-
locale,
|
|
2287
|
-
requestTimeout,
|
|
2288
|
-
plugins = [],
|
|
2289
|
-
onLog,
|
|
2290
|
-
onError,
|
|
2291
|
-
componentViewTrackingThreshold
|
|
2292
|
-
} = props;
|
|
2293
|
-
return new experience_js.Ninetailed({
|
|
2294
|
-
clientId,
|
|
2295
|
-
environment,
|
|
2296
|
-
preview
|
|
2297
|
-
}, {
|
|
2298
|
-
url,
|
|
2299
|
-
plugins,
|
|
2300
|
-
profile,
|
|
2301
|
-
locale,
|
|
2302
|
-
requestTimeout,
|
|
2303
|
-
onLog,
|
|
2304
|
-
onError,
|
|
2305
|
-
componentViewTrackingThreshold
|
|
2306
|
-
});
|
|
2307
|
-
}, []);
|
|
2308
|
-
const {
|
|
2309
|
-
experiments = [],
|
|
2310
|
-
maximumActiveExperiments,
|
|
2311
|
-
children
|
|
2312
|
-
} = props;
|
|
2313
|
-
return jsxRuntime.jsx(NinetailedContext.Provider, Object.assign({
|
|
2314
|
-
value: ninetailed
|
|
2315
|
-
}, {
|
|
2316
|
-
children: jsxRuntime.jsx(ExperimentsProvider, Object.assign({
|
|
2317
|
-
experiments: experiments,
|
|
2318
|
-
maximumActiveExperiments: maximumActiveExperiments
|
|
2319
|
-
}, {
|
|
2320
|
-
children: children
|
|
2321
|
-
}))
|
|
2322
|
-
}));
|
|
2323
|
-
};
|
|
2324
|
-
|
|
2325
|
-
const usePersonalize = (baseline, variants, options = {
|
|
2326
|
-
holdout: -1
|
|
2327
|
-
}) => {
|
|
2328
|
-
const profile = useProfile();
|
|
2329
|
-
return experience_js.selectVariant(baseline, variants, profile, options);
|
|
2330
|
-
};
|
|
2331
|
-
|
|
2332
|
-
const TrackHasSeenComponent = ({
|
|
2333
|
-
children,
|
|
2334
|
-
variant,
|
|
2335
|
-
audience,
|
|
2336
|
-
isPersonalized
|
|
2337
|
-
}) => {
|
|
2338
|
-
const ninetailed = useNinetailed();
|
|
2339
|
-
const {
|
|
2340
|
-
ref,
|
|
2341
|
-
inView
|
|
2342
|
-
} = reactIntersectionObserver.useInView({
|
|
2343
|
-
triggerOnce: true
|
|
2344
|
-
});
|
|
2345
|
-
React.useEffect(() => {
|
|
2346
|
-
if (experience_jsShared.isBrowser() && inView) {
|
|
2347
|
-
ninetailed.trackHasSeenComponent({
|
|
2348
|
-
variant,
|
|
2349
|
-
audience,
|
|
2350
|
-
isPersonalized
|
|
2351
|
-
});
|
|
2352
|
-
}
|
|
2353
|
-
}, [inView]);
|
|
2354
|
-
return jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
2355
|
-
children: [jsxRuntime.jsx("div", {
|
|
2356
|
-
ref: ref
|
|
2357
|
-
}), children]
|
|
2358
|
-
});
|
|
2359
|
-
};
|
|
2360
|
-
|
|
2361
|
-
const Personalize = _a => {
|
|
2362
|
-
var {
|
|
2363
|
-
component: Component,
|
|
2364
|
-
loadingComponent: LoadingComponent,
|
|
2365
|
-
variants = [],
|
|
2366
|
-
holdout = -1
|
|
2367
|
-
} = _a,
|
|
2368
|
-
baseline = __rest(_a, ["component", "loadingComponent", "variants", "holdout"]);
|
|
2369
|
-
const {
|
|
2370
|
-
loading,
|
|
2371
|
-
variant,
|
|
2372
|
-
isPersonalized,
|
|
2373
|
-
audience
|
|
2374
|
-
} = usePersonalize(baseline, variants, {
|
|
2375
|
-
holdout
|
|
2376
|
-
});
|
|
2377
|
-
const hasVariants = variants.length > 0;
|
|
2378
|
-
if (!hasVariants) {
|
|
2379
|
-
return jsxRuntime.jsx(Component, Object.assign({}, baseline, {
|
|
2380
|
-
ninetailed: {
|
|
2381
|
-
isPersonalized,
|
|
2382
|
-
audience
|
|
2383
|
-
}
|
|
2384
|
-
}));
|
|
2385
|
-
}
|
|
2386
|
-
if (loading) {
|
|
2387
|
-
if (LoadingComponent) {
|
|
2388
|
-
return jsxRuntime.jsx(LoadingComponent, {});
|
|
2389
|
-
}
|
|
2390
|
-
return jsxRuntime.jsx("div", Object.assign({
|
|
2391
|
-
style: {
|
|
2392
|
-
opacity: 0
|
|
2393
|
-
}
|
|
2394
|
-
}, {
|
|
2395
|
-
children: jsxRuntime.jsx(Component, Object.assign({}, variant, {
|
|
2396
|
-
ninetailed: {
|
|
2397
|
-
isPersonalized,
|
|
2398
|
-
audience
|
|
2399
|
-
}
|
|
2400
|
-
}))
|
|
2401
|
-
}), "hide");
|
|
2402
|
-
}
|
|
2403
|
-
return jsxRuntime.jsx(TrackHasSeenComponent, Object.assign({
|
|
2404
|
-
variant: variant,
|
|
2405
|
-
audience: audience,
|
|
2406
|
-
isPersonalized: isPersonalized
|
|
2407
|
-
}, {
|
|
2408
|
-
children: /*#__PURE__*/React.createElement(Component, Object.assign({}, variant, {
|
|
2409
|
-
key: `${audience.id}-${variant.id}`,
|
|
2410
|
-
ninetailed: {
|
|
2411
|
-
isPersonalized,
|
|
2412
|
-
audience
|
|
2413
|
-
}
|
|
2414
|
-
}))
|
|
2415
|
-
}));
|
|
2416
|
-
};
|
|
2417
|
-
|
|
2418
|
-
const generateSelectors = id => {
|
|
2419
|
-
return id.split('_').map((path, index, paths) => {
|
|
2420
|
-
const dotPath = paths.slice(0, index).join('.');
|
|
2421
|
-
const underScorePath = paths.slice(index).join('_');
|
|
2422
|
-
return [dotPath, underScorePath].filter(path => path !== '').join('.');
|
|
2423
|
-
});
|
|
2424
|
-
};
|
|
2425
|
-
const selectValueFromProfile = (profile, id) => {
|
|
2426
|
-
const selectors = generateSelectors(id);
|
|
2427
|
-
const matchingSelector = selectors.find(selector => radash.get(profile, selector));
|
|
2428
|
-
if (!matchingSelector) {
|
|
2429
|
-
return null;
|
|
2430
|
-
}
|
|
2431
|
-
return radash.get(profile, matchingSelector);
|
|
2432
|
-
};
|
|
2433
|
-
const MergeTag = ({
|
|
2434
|
-
id
|
|
2435
|
-
}) => {
|
|
2436
|
-
const {
|
|
2437
|
-
loading,
|
|
2438
|
-
profile
|
|
2439
|
-
} = useProfile();
|
|
2440
|
-
if (loading || !profile) {
|
|
2441
|
-
return null;
|
|
2442
|
-
}
|
|
2443
|
-
const value = selectValueFromProfile(profile, id);
|
|
2444
|
-
// DON'T CHANGE
|
|
2445
|
-
return jsxRuntime.jsx(jsxRuntime.Fragment, {
|
|
2446
|
-
children: value
|
|
2447
|
-
});
|
|
2448
|
-
};
|
|
2449
|
-
|
|
2450
2322
|
exports.DefaultExperienceLoadingComponent = DefaultExperienceLoadingComponent;
|
|
2451
2323
|
exports.ESRLoadingComponent = ESRLoadingComponent;
|
|
2452
2324
|
exports.ESRProvider = ESRProvider;
|
|
2453
2325
|
exports.Experience = Experience;
|
|
2454
|
-
exports.ExperimentsProvider = ExperimentsProvider;
|
|
2455
2326
|
exports.MergeTag = MergeTag;
|
|
2456
2327
|
exports.NinetailedProvider = NinetailedProvider;
|
|
2457
2328
|
exports.Personalize = Personalize;
|
|
2458
2329
|
exports.TrackHasSeenComponent = TrackHasSeenComponent;
|
|
2459
2330
|
exports.useExperience = useExperience;
|
|
2460
|
-
exports.useExperiments = useExperiments;
|
|
2461
|
-
exports.useJoinExperiment = useJoinExperiment;
|
|
2462
2331
|
exports.useNinetailed = useNinetailed;
|
|
2463
2332
|
exports.usePersonalize = usePersonalize;
|
|
2464
2333
|
exports.useProfile = useProfile;
|
package/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import React, { createContext, useContext, useState, useRef, useEffect,
|
|
3
|
-
import { makeExperienceSelectMiddleware, selectHasExperienceVariants,
|
|
4
|
-
import { isForwardRef } from 'react-is';
|
|
2
|
+
import React, { createContext, useMemo, useContext, useState, useRef, useEffect, createElement as createElement$1, forwardRef } from 'react';
|
|
3
|
+
import { Ninetailed, selectVariant, makeExperienceSelectMiddleware, selectHasExperienceVariants, selectExperience, selectExperienceVariant } from '@ninetailed/experience.js';
|
|
5
4
|
import { logger, isBrowser } from '@ninetailed/experience.js-shared';
|
|
6
|
-
import { isEqual,
|
|
5
|
+
import { isEqual, get as get$1 } from 'radash';
|
|
7
6
|
import { useInView } from 'react-intersection-observer';
|
|
7
|
+
import { isForwardRef } from 'react-is';
|
|
8
8
|
|
|
9
9
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
10
10
|
|
|
@@ -1091,6 +1091,57 @@ $$2({ target: 'Object', stat: true, arity: 2, forced: Object.assign !== assign }
|
|
|
1091
1091
|
|
|
1092
1092
|
const NinetailedContext = /*#__PURE__*/createContext(undefined);
|
|
1093
1093
|
|
|
1094
|
+
const NinetailedProvider = props => {
|
|
1095
|
+
const ninetailed = useMemo(() => {
|
|
1096
|
+
if ('ninetailed' in props) {
|
|
1097
|
+
return props.ninetailed;
|
|
1098
|
+
}
|
|
1099
|
+
const {
|
|
1100
|
+
clientId,
|
|
1101
|
+
environment,
|
|
1102
|
+
preview,
|
|
1103
|
+
url,
|
|
1104
|
+
profile,
|
|
1105
|
+
locale,
|
|
1106
|
+
requestTimeout,
|
|
1107
|
+
plugins = [],
|
|
1108
|
+
onLog,
|
|
1109
|
+
onError,
|
|
1110
|
+
componentViewTrackingThreshold
|
|
1111
|
+
} = props;
|
|
1112
|
+
return new Ninetailed({
|
|
1113
|
+
clientId,
|
|
1114
|
+
environment,
|
|
1115
|
+
preview
|
|
1116
|
+
}, {
|
|
1117
|
+
url,
|
|
1118
|
+
plugins,
|
|
1119
|
+
profile,
|
|
1120
|
+
locale,
|
|
1121
|
+
requestTimeout,
|
|
1122
|
+
onLog,
|
|
1123
|
+
onError,
|
|
1124
|
+
componentViewTrackingThreshold
|
|
1125
|
+
});
|
|
1126
|
+
}, []);
|
|
1127
|
+
const {
|
|
1128
|
+
children
|
|
1129
|
+
} = props;
|
|
1130
|
+
return jsx(NinetailedContext.Provider, Object.assign({
|
|
1131
|
+
value: ninetailed
|
|
1132
|
+
}, {
|
|
1133
|
+
children: children
|
|
1134
|
+
}));
|
|
1135
|
+
};
|
|
1136
|
+
|
|
1137
|
+
const useNinetailed = () => {
|
|
1138
|
+
const ninetailed = useContext(NinetailedContext);
|
|
1139
|
+
if (ninetailed === undefined) {
|
|
1140
|
+
throw new Error('The component using the the context must be a descendant of the NinetailedProvider');
|
|
1141
|
+
}
|
|
1142
|
+
return ninetailed;
|
|
1143
|
+
};
|
|
1144
|
+
|
|
1094
1145
|
var objectDefineProperties = {};
|
|
1095
1146
|
|
|
1096
1147
|
var DESCRIPTORS$1 = descriptors;
|
|
@@ -1618,6 +1669,49 @@ for (var COLLECTION_NAME in DOMIterables) {
|
|
|
1618
1669
|
|
|
1619
1670
|
handlePrototype(DOMTokenListPrototype, 'DOMTokenList');
|
|
1620
1671
|
|
|
1672
|
+
const useProfile = () => {
|
|
1673
|
+
const ninetailed = useNinetailed();
|
|
1674
|
+
const [profileState, setProfileState] = useState(ninetailed.profileState);
|
|
1675
|
+
const profileStateRef = useRef({});
|
|
1676
|
+
/**
|
|
1677
|
+
* This effect compares the old and new profile state before updating it.
|
|
1678
|
+
* We use a ref to avoid an infinite loop which can happen when an empty profile state was updated with no changes.
|
|
1679
|
+
* This behaviour occurred as the validation handling on the error property was not set properly in the "CreateProfile" and "UpdateProfile" endpoint types.
|
|
1680
|
+
* Furthermore, it was also observed, that it "only" occurred when the preview plugin was used in parallel.
|
|
1681
|
+
*/
|
|
1682
|
+
useEffect(() => {
|
|
1683
|
+
ninetailed.onProfileChange(profileState => {
|
|
1684
|
+
if (isEqual(profileState, profileStateRef.current)) {
|
|
1685
|
+
logger.debug('Profile State Did Not Change', profileState);
|
|
1686
|
+
return;
|
|
1687
|
+
} else {
|
|
1688
|
+
setProfileState(profileState);
|
|
1689
|
+
profileStateRef.current = profileState;
|
|
1690
|
+
logger.debug('Profile State Changed', profileState);
|
|
1691
|
+
}
|
|
1692
|
+
});
|
|
1693
|
+
}, []);
|
|
1694
|
+
/**
|
|
1695
|
+
* Old implementation without profile state deep comparison
|
|
1696
|
+
*/
|
|
1697
|
+
/*useEffect(() => {
|
|
1698
|
+
return ninetailed.onProfileChange((profileState) => {
|
|
1699
|
+
console.log('profileState', profileState);
|
|
1700
|
+
setProfileState(profileState);
|
|
1701
|
+
});
|
|
1702
|
+
}, []);*/
|
|
1703
|
+
return Object.assign(Object.assign({}, profileState), {
|
|
1704
|
+
loading: profileState.status === 'loading'
|
|
1705
|
+
});
|
|
1706
|
+
};
|
|
1707
|
+
|
|
1708
|
+
const usePersonalize = (baseline, variants, options = {
|
|
1709
|
+
holdout: -1
|
|
1710
|
+
}) => {
|
|
1711
|
+
const profile = useProfile();
|
|
1712
|
+
return selectVariant(baseline, variants, profile, options);
|
|
1713
|
+
};
|
|
1714
|
+
|
|
1621
1715
|
/******************************************************************************
|
|
1622
1716
|
Copyright (c) Microsoft Corporation.
|
|
1623
1717
|
|
|
@@ -1643,18 +1737,126 @@ function __rest(s, e) {
|
|
|
1643
1737
|
t[p[i]] = s[p[i]];
|
|
1644
1738
|
}
|
|
1645
1739
|
return t;
|
|
1646
|
-
}
|
|
1647
|
-
|
|
1648
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
1649
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
1650
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
1651
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
1652
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
1653
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
1654
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1655
|
-
});
|
|
1656
1740
|
}
|
|
1657
1741
|
|
|
1742
|
+
const TrackHasSeenComponent = ({
|
|
1743
|
+
children,
|
|
1744
|
+
variant,
|
|
1745
|
+
audience,
|
|
1746
|
+
isPersonalized
|
|
1747
|
+
}) => {
|
|
1748
|
+
const ninetailed = useNinetailed();
|
|
1749
|
+
const {
|
|
1750
|
+
ref,
|
|
1751
|
+
inView
|
|
1752
|
+
} = useInView({
|
|
1753
|
+
triggerOnce: true
|
|
1754
|
+
});
|
|
1755
|
+
useEffect(() => {
|
|
1756
|
+
if (isBrowser() && inView) {
|
|
1757
|
+
ninetailed.trackHasSeenComponent({
|
|
1758
|
+
variant,
|
|
1759
|
+
audience,
|
|
1760
|
+
isPersonalized
|
|
1761
|
+
});
|
|
1762
|
+
}
|
|
1763
|
+
}, [inView]);
|
|
1764
|
+
return jsxs(Fragment, {
|
|
1765
|
+
children: [jsx("div", {
|
|
1766
|
+
ref: ref
|
|
1767
|
+
}), children]
|
|
1768
|
+
});
|
|
1769
|
+
};
|
|
1770
|
+
|
|
1771
|
+
const Personalize = _a => {
|
|
1772
|
+
var {
|
|
1773
|
+
component: Component,
|
|
1774
|
+
loadingComponent: LoadingComponent,
|
|
1775
|
+
variants = [],
|
|
1776
|
+
holdout = -1
|
|
1777
|
+
} = _a,
|
|
1778
|
+
baseline = __rest(_a, ["component", "loadingComponent", "variants", "holdout"]);
|
|
1779
|
+
const {
|
|
1780
|
+
loading,
|
|
1781
|
+
variant,
|
|
1782
|
+
isPersonalized,
|
|
1783
|
+
audience
|
|
1784
|
+
} = usePersonalize(baseline, variants, {
|
|
1785
|
+
holdout
|
|
1786
|
+
});
|
|
1787
|
+
const hasVariants = variants.length > 0;
|
|
1788
|
+
if (!hasVariants) {
|
|
1789
|
+
return jsx(Component, Object.assign({}, baseline, {
|
|
1790
|
+
ninetailed: {
|
|
1791
|
+
isPersonalized,
|
|
1792
|
+
audience
|
|
1793
|
+
}
|
|
1794
|
+
}));
|
|
1795
|
+
}
|
|
1796
|
+
if (loading) {
|
|
1797
|
+
if (LoadingComponent) {
|
|
1798
|
+
return jsx(LoadingComponent, {});
|
|
1799
|
+
}
|
|
1800
|
+
return jsx("div", Object.assign({
|
|
1801
|
+
style: {
|
|
1802
|
+
opacity: 0
|
|
1803
|
+
}
|
|
1804
|
+
}, {
|
|
1805
|
+
children: jsx(Component, Object.assign({}, variant, {
|
|
1806
|
+
ninetailed: {
|
|
1807
|
+
isPersonalized,
|
|
1808
|
+
audience
|
|
1809
|
+
}
|
|
1810
|
+
}))
|
|
1811
|
+
}), "hide");
|
|
1812
|
+
}
|
|
1813
|
+
return jsx(TrackHasSeenComponent, Object.assign({
|
|
1814
|
+
variant: variant,
|
|
1815
|
+
audience: audience,
|
|
1816
|
+
isPersonalized: isPersonalized
|
|
1817
|
+
}, {
|
|
1818
|
+
children: /*#__PURE__*/createElement$1(Component, Object.assign({}, variant, {
|
|
1819
|
+
key: `${audience.id}-${variant.id}`,
|
|
1820
|
+
ninetailed: {
|
|
1821
|
+
isPersonalized,
|
|
1822
|
+
audience
|
|
1823
|
+
}
|
|
1824
|
+
}))
|
|
1825
|
+
}));
|
|
1826
|
+
};
|
|
1827
|
+
|
|
1828
|
+
const generateSelectors = id => {
|
|
1829
|
+
return id.split('_').map((path, index, paths) => {
|
|
1830
|
+
const dotPath = paths.slice(0, index).join('.');
|
|
1831
|
+
const underScorePath = paths.slice(index).join('_');
|
|
1832
|
+
return [dotPath, underScorePath].filter(path => path !== '').join('.');
|
|
1833
|
+
});
|
|
1834
|
+
};
|
|
1835
|
+
const selectValueFromProfile = (profile, id) => {
|
|
1836
|
+
const selectors = generateSelectors(id);
|
|
1837
|
+
const matchingSelector = selectors.find(selector => get$1(profile, selector));
|
|
1838
|
+
if (!matchingSelector) {
|
|
1839
|
+
return null;
|
|
1840
|
+
}
|
|
1841
|
+
return get$1(profile, matchingSelector);
|
|
1842
|
+
};
|
|
1843
|
+
const MergeTag = ({
|
|
1844
|
+
id
|
|
1845
|
+
}) => {
|
|
1846
|
+
const {
|
|
1847
|
+
loading,
|
|
1848
|
+
profile
|
|
1849
|
+
} = useProfile();
|
|
1850
|
+
if (loading || !profile) {
|
|
1851
|
+
return null;
|
|
1852
|
+
}
|
|
1853
|
+
const value = selectValueFromProfile(profile, id);
|
|
1854
|
+
// DON'T CHANGE
|
|
1855
|
+
return jsx(Fragment, {
|
|
1856
|
+
children: value
|
|
1857
|
+
});
|
|
1858
|
+
};
|
|
1859
|
+
|
|
1658
1860
|
var aCallable = aCallable$2;
|
|
1659
1861
|
var toObject = toObject$4;
|
|
1660
1862
|
var IndexedObject = indexedObject;
|
|
@@ -1733,67 +1935,6 @@ $({ target: 'Array', proto: true, forced: !STRICT_METHOD || CHROME_BUG }, {
|
|
|
1733
1935
|
}
|
|
1734
1936
|
});
|
|
1735
1937
|
|
|
1736
|
-
const useNinetailed = () => {
|
|
1737
|
-
const ninetailed = useContext(NinetailedContext);
|
|
1738
|
-
if (ninetailed === undefined) {
|
|
1739
|
-
throw new Error('The component using the the context must be a descendant of the NinetailedProvider');
|
|
1740
|
-
}
|
|
1741
|
-
return ninetailed;
|
|
1742
|
-
};
|
|
1743
|
-
|
|
1744
|
-
const useProfile = () => {
|
|
1745
|
-
const ninetailed = useNinetailed();
|
|
1746
|
-
const [profileState, setProfileState] = useState(ninetailed.profileState);
|
|
1747
|
-
const profileStateRef = useRef({});
|
|
1748
|
-
/**
|
|
1749
|
-
* This effect compares the old and new profile state before updating it.
|
|
1750
|
-
* We use a ref to avoid an infinite loop which can happen when an empty profile state was updated with no changes.
|
|
1751
|
-
* This behaviour occurred as the validation handling on the error property was not set properly in the "CreateProfile" and "UpdateProfile" endpoint types.
|
|
1752
|
-
* Furthermore, it was also observed, that it "only" occurred when the preview plugin was used in parallel.
|
|
1753
|
-
*/
|
|
1754
|
-
useEffect(() => {
|
|
1755
|
-
ninetailed.onProfileChange(profileState => {
|
|
1756
|
-
if (isEqual(profileState, profileStateRef.current)) {
|
|
1757
|
-
logger.debug('Profile State Did Not Change', profileState);
|
|
1758
|
-
return;
|
|
1759
|
-
} else {
|
|
1760
|
-
setProfileState(profileState);
|
|
1761
|
-
profileStateRef.current = profileState;
|
|
1762
|
-
logger.debug('Profile State Changed', profileState);
|
|
1763
|
-
}
|
|
1764
|
-
});
|
|
1765
|
-
}, []);
|
|
1766
|
-
/**
|
|
1767
|
-
* Old implementation without profile state deep comparison
|
|
1768
|
-
*/
|
|
1769
|
-
/*useEffect(() => {
|
|
1770
|
-
return ninetailed.onProfileChange((profileState) => {
|
|
1771
|
-
console.log('profileState', profileState);
|
|
1772
|
-
setProfileState(profileState);
|
|
1773
|
-
});
|
|
1774
|
-
}, []);*/
|
|
1775
|
-
return Object.assign(Object.assign({}, profileState), {
|
|
1776
|
-
loading: profileState.status === 'loading'
|
|
1777
|
-
});
|
|
1778
|
-
};
|
|
1779
|
-
|
|
1780
|
-
const ExperimentsContext = /*#__PURE__*/createContext(undefined);
|
|
1781
|
-
|
|
1782
|
-
const useExperimentsContext = () => {
|
|
1783
|
-
const context = useContext(ExperimentsContext);
|
|
1784
|
-
if (context === undefined) {
|
|
1785
|
-
throw new Error('The component using the the context must be a descendant of the ExperimentsProvider');
|
|
1786
|
-
}
|
|
1787
|
-
return context;
|
|
1788
|
-
};
|
|
1789
|
-
|
|
1790
|
-
const useExperiments = () => {
|
|
1791
|
-
const context = useExperimentsContext();
|
|
1792
|
-
return {
|
|
1793
|
-
experiments: context.experiments
|
|
1794
|
-
};
|
|
1795
|
-
};
|
|
1796
|
-
|
|
1797
1938
|
const useExperienceSelectionMiddleware = ({
|
|
1798
1939
|
experiences,
|
|
1799
1940
|
baseline,
|
|
@@ -1828,9 +1969,6 @@ const useExperience = ({
|
|
|
1828
1969
|
experiences
|
|
1829
1970
|
}) => {
|
|
1830
1971
|
const profileState = useProfile();
|
|
1831
|
-
const {
|
|
1832
|
-
experiments
|
|
1833
|
-
} = useExperiments();
|
|
1834
1972
|
const hasVariants = experiences.map(experience => selectHasExperienceVariants(experience, baseline)).reduce((acc, curr) => acc || curr, false);
|
|
1835
1973
|
const {
|
|
1836
1974
|
status,
|
|
@@ -1893,10 +2031,8 @@ const useExperience = ({
|
|
|
1893
2031
|
// @ts-ignore
|
|
1894
2032
|
return overrideResult(emptyReturn);
|
|
1895
2033
|
}
|
|
1896
|
-
const activeExperiments = selectActiveExperiments(experiments, profile);
|
|
1897
2034
|
const experience = selectExperience({
|
|
1898
2035
|
experiences,
|
|
1899
|
-
activeExperiments,
|
|
1900
2036
|
profile
|
|
1901
2037
|
});
|
|
1902
2038
|
if (!experience) {
|
|
@@ -1927,11 +2063,6 @@ const useExperience = ({
|
|
|
1927
2063
|
}));
|
|
1928
2064
|
};
|
|
1929
2065
|
|
|
1930
|
-
const useJoinExperiment = () => {
|
|
1931
|
-
const context = useExperimentsContext();
|
|
1932
|
-
return context.joinExperiment;
|
|
1933
|
-
};
|
|
1934
|
-
|
|
1935
2066
|
const ComponentMarker = /*#__PURE__*/forwardRef((_, ref) => {
|
|
1936
2067
|
const {
|
|
1937
2068
|
logger
|
|
@@ -2027,26 +2158,15 @@ const Experience = _a => {
|
|
|
2027
2158
|
variant,
|
|
2028
2159
|
variantIndex,
|
|
2029
2160
|
audience,
|
|
2030
|
-
isPersonalized
|
|
2031
|
-
profile
|
|
2161
|
+
isPersonalized
|
|
2032
2162
|
} = useExperience({
|
|
2033
2163
|
baseline,
|
|
2034
2164
|
experiences
|
|
2035
2165
|
});
|
|
2036
|
-
const joinExperiment = useJoinExperiment();
|
|
2037
2166
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2038
2167
|
// @ts-ignore
|
|
2039
2168
|
const isComponentForwardRef = isForwardRef(jsx(Component, {}));
|
|
2040
2169
|
const componentRef = useRef(null);
|
|
2041
|
-
useEffect(() => {
|
|
2042
|
-
if (status === 'success' && experience && profile) {
|
|
2043
|
-
joinExperiment({
|
|
2044
|
-
experiences,
|
|
2045
|
-
experiment: experience,
|
|
2046
|
-
profile
|
|
2047
|
-
});
|
|
2048
|
-
}
|
|
2049
|
-
}, [status, experience, profile]);
|
|
2050
2170
|
useEffect(() => {
|
|
2051
2171
|
const componentElement = componentRef.current;
|
|
2052
2172
|
if (componentElement) {
|
|
@@ -2191,252 +2311,4 @@ const ESRLoadingComponent = _a => {
|
|
|
2191
2311
|
}));
|
|
2192
2312
|
};
|
|
2193
2313
|
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
const debounce = (fn, wait) => {
|
|
2197
|
-
let debouncedArgs = [];
|
|
2198
|
-
const debouncedFn = debounce$1({
|
|
2199
|
-
delay: wait !== null && wait !== void 0 ? wait : 0
|
|
2200
|
-
}, () => {
|
|
2201
|
-
fn.call(undefined, debouncedArgs);
|
|
2202
|
-
debouncedArgs = [];
|
|
2203
|
-
});
|
|
2204
|
-
return (...args) => {
|
|
2205
|
-
debouncedArgs.push(args);
|
|
2206
|
-
debouncedFn();
|
|
2207
|
-
};
|
|
2208
|
-
};
|
|
2209
|
-
const useProvideJoinExperiment = ({
|
|
2210
|
-
experiments,
|
|
2211
|
-
maximumActiveExperiments: _maximumActiveExperiments = 1
|
|
2212
|
-
}) => {
|
|
2213
|
-
const {
|
|
2214
|
-
identify
|
|
2215
|
-
} = useNinetailed();
|
|
2216
|
-
const joinExperimentIdentify = debounce(args => {
|
|
2217
|
-
const traits = args.slice(0, _maximumActiveExperiments).reduce((traits, [experimentJoinTraits]) => {
|
|
2218
|
-
return Object.assign(Object.assign({}, experimentJoinTraits), traits);
|
|
2219
|
-
}, {});
|
|
2220
|
-
identify('', traits);
|
|
2221
|
-
});
|
|
2222
|
-
return useCallback(data => __awaiter(void 0, void 0, void 0, function* () {
|
|
2223
|
-
const {
|
|
2224
|
-
experiment,
|
|
2225
|
-
profile
|
|
2226
|
-
} = data;
|
|
2227
|
-
const isExperiment = experiment.type === 'nt_experiment';
|
|
2228
|
-
if (!isExperiment) {
|
|
2229
|
-
logger.warn(`The experience ${experiment.id}, which you tried to join, is not an experiment.`);
|
|
2230
|
-
return;
|
|
2231
|
-
}
|
|
2232
|
-
const activeExperiments = selectActiveExperiments(experiments, profile);
|
|
2233
|
-
if (activeExperiments.length >= _maximumActiveExperiments) {
|
|
2234
|
-
logger.warn(`The maximum number of active experiments (${_maximumActiveExperiments}) has been reached.`);
|
|
2235
|
-
return;
|
|
2236
|
-
}
|
|
2237
|
-
if (activeExperiments.some(activeExperiment => activeExperiment.id === experiment.id)) {
|
|
2238
|
-
logger.debug(`The user is already part of experiment ${experiment.id}. Won't join again.`);
|
|
2239
|
-
return;
|
|
2240
|
-
}
|
|
2241
|
-
joinExperimentIdentify({
|
|
2242
|
-
[`${EXPERIENCE_TRAIT_PREFIX}${experiment.id}`]: true
|
|
2243
|
-
});
|
|
2244
|
-
logger.debug(`Sent event to join experiment ${experiment.id}.`);
|
|
2245
|
-
}), []);
|
|
2246
|
-
};
|
|
2247
|
-
|
|
2248
|
-
const ExperimentsProvider = ({
|
|
2249
|
-
experiments,
|
|
2250
|
-
maximumActiveExperiments: _maximumActiveExperiments = 1,
|
|
2251
|
-
children
|
|
2252
|
-
}) => {
|
|
2253
|
-
const joinExperiment = useProvideJoinExperiment({
|
|
2254
|
-
experiments,
|
|
2255
|
-
maximumActiveExperiments: _maximumActiveExperiments
|
|
2256
|
-
});
|
|
2257
|
-
return jsx(ExperimentsContext.Provider, Object.assign({
|
|
2258
|
-
value: {
|
|
2259
|
-
experiments,
|
|
2260
|
-
joinExperiment
|
|
2261
|
-
}
|
|
2262
|
-
}, {
|
|
2263
|
-
children: children
|
|
2264
|
-
}));
|
|
2265
|
-
};
|
|
2266
|
-
|
|
2267
|
-
const NinetailedProvider = props => {
|
|
2268
|
-
const ninetailed = useMemo(() => {
|
|
2269
|
-
if ('ninetailed' in props) {
|
|
2270
|
-
return props.ninetailed;
|
|
2271
|
-
}
|
|
2272
|
-
const {
|
|
2273
|
-
clientId,
|
|
2274
|
-
environment,
|
|
2275
|
-
preview,
|
|
2276
|
-
url,
|
|
2277
|
-
profile,
|
|
2278
|
-
locale,
|
|
2279
|
-
requestTimeout,
|
|
2280
|
-
plugins = [],
|
|
2281
|
-
onLog,
|
|
2282
|
-
onError,
|
|
2283
|
-
componentViewTrackingThreshold
|
|
2284
|
-
} = props;
|
|
2285
|
-
return new Ninetailed({
|
|
2286
|
-
clientId,
|
|
2287
|
-
environment,
|
|
2288
|
-
preview
|
|
2289
|
-
}, {
|
|
2290
|
-
url,
|
|
2291
|
-
plugins,
|
|
2292
|
-
profile,
|
|
2293
|
-
locale,
|
|
2294
|
-
requestTimeout,
|
|
2295
|
-
onLog,
|
|
2296
|
-
onError,
|
|
2297
|
-
componentViewTrackingThreshold
|
|
2298
|
-
});
|
|
2299
|
-
}, []);
|
|
2300
|
-
const {
|
|
2301
|
-
experiments = [],
|
|
2302
|
-
maximumActiveExperiments,
|
|
2303
|
-
children
|
|
2304
|
-
} = props;
|
|
2305
|
-
return jsx(NinetailedContext.Provider, Object.assign({
|
|
2306
|
-
value: ninetailed
|
|
2307
|
-
}, {
|
|
2308
|
-
children: jsx(ExperimentsProvider, Object.assign({
|
|
2309
|
-
experiments: experiments,
|
|
2310
|
-
maximumActiveExperiments: maximumActiveExperiments
|
|
2311
|
-
}, {
|
|
2312
|
-
children: children
|
|
2313
|
-
}))
|
|
2314
|
-
}));
|
|
2315
|
-
};
|
|
2316
|
-
|
|
2317
|
-
const usePersonalize = (baseline, variants, options = {
|
|
2318
|
-
holdout: -1
|
|
2319
|
-
}) => {
|
|
2320
|
-
const profile = useProfile();
|
|
2321
|
-
return selectVariant(baseline, variants, profile, options);
|
|
2322
|
-
};
|
|
2323
|
-
|
|
2324
|
-
const TrackHasSeenComponent = ({
|
|
2325
|
-
children,
|
|
2326
|
-
variant,
|
|
2327
|
-
audience,
|
|
2328
|
-
isPersonalized
|
|
2329
|
-
}) => {
|
|
2330
|
-
const ninetailed = useNinetailed();
|
|
2331
|
-
const {
|
|
2332
|
-
ref,
|
|
2333
|
-
inView
|
|
2334
|
-
} = useInView({
|
|
2335
|
-
triggerOnce: true
|
|
2336
|
-
});
|
|
2337
|
-
useEffect(() => {
|
|
2338
|
-
if (isBrowser() && inView) {
|
|
2339
|
-
ninetailed.trackHasSeenComponent({
|
|
2340
|
-
variant,
|
|
2341
|
-
audience,
|
|
2342
|
-
isPersonalized
|
|
2343
|
-
});
|
|
2344
|
-
}
|
|
2345
|
-
}, [inView]);
|
|
2346
|
-
return jsxs(Fragment, {
|
|
2347
|
-
children: [jsx("div", {
|
|
2348
|
-
ref: ref
|
|
2349
|
-
}), children]
|
|
2350
|
-
});
|
|
2351
|
-
};
|
|
2352
|
-
|
|
2353
|
-
const Personalize = _a => {
|
|
2354
|
-
var {
|
|
2355
|
-
component: Component,
|
|
2356
|
-
loadingComponent: LoadingComponent,
|
|
2357
|
-
variants = [],
|
|
2358
|
-
holdout = -1
|
|
2359
|
-
} = _a,
|
|
2360
|
-
baseline = __rest(_a, ["component", "loadingComponent", "variants", "holdout"]);
|
|
2361
|
-
const {
|
|
2362
|
-
loading,
|
|
2363
|
-
variant,
|
|
2364
|
-
isPersonalized,
|
|
2365
|
-
audience
|
|
2366
|
-
} = usePersonalize(baseline, variants, {
|
|
2367
|
-
holdout
|
|
2368
|
-
});
|
|
2369
|
-
const hasVariants = variants.length > 0;
|
|
2370
|
-
if (!hasVariants) {
|
|
2371
|
-
return jsx(Component, Object.assign({}, baseline, {
|
|
2372
|
-
ninetailed: {
|
|
2373
|
-
isPersonalized,
|
|
2374
|
-
audience
|
|
2375
|
-
}
|
|
2376
|
-
}));
|
|
2377
|
-
}
|
|
2378
|
-
if (loading) {
|
|
2379
|
-
if (LoadingComponent) {
|
|
2380
|
-
return jsx(LoadingComponent, {});
|
|
2381
|
-
}
|
|
2382
|
-
return jsx("div", Object.assign({
|
|
2383
|
-
style: {
|
|
2384
|
-
opacity: 0
|
|
2385
|
-
}
|
|
2386
|
-
}, {
|
|
2387
|
-
children: jsx(Component, Object.assign({}, variant, {
|
|
2388
|
-
ninetailed: {
|
|
2389
|
-
isPersonalized,
|
|
2390
|
-
audience
|
|
2391
|
-
}
|
|
2392
|
-
}))
|
|
2393
|
-
}), "hide");
|
|
2394
|
-
}
|
|
2395
|
-
return jsx(TrackHasSeenComponent, Object.assign({
|
|
2396
|
-
variant: variant,
|
|
2397
|
-
audience: audience,
|
|
2398
|
-
isPersonalized: isPersonalized
|
|
2399
|
-
}, {
|
|
2400
|
-
children: /*#__PURE__*/createElement$1(Component, Object.assign({}, variant, {
|
|
2401
|
-
key: `${audience.id}-${variant.id}`,
|
|
2402
|
-
ninetailed: {
|
|
2403
|
-
isPersonalized,
|
|
2404
|
-
audience
|
|
2405
|
-
}
|
|
2406
|
-
}))
|
|
2407
|
-
}));
|
|
2408
|
-
};
|
|
2409
|
-
|
|
2410
|
-
const generateSelectors = id => {
|
|
2411
|
-
return id.split('_').map((path, index, paths) => {
|
|
2412
|
-
const dotPath = paths.slice(0, index).join('.');
|
|
2413
|
-
const underScorePath = paths.slice(index).join('_');
|
|
2414
|
-
return [dotPath, underScorePath].filter(path => path !== '').join('.');
|
|
2415
|
-
});
|
|
2416
|
-
};
|
|
2417
|
-
const selectValueFromProfile = (profile, id) => {
|
|
2418
|
-
const selectors = generateSelectors(id);
|
|
2419
|
-
const matchingSelector = selectors.find(selector => get$1(profile, selector));
|
|
2420
|
-
if (!matchingSelector) {
|
|
2421
|
-
return null;
|
|
2422
|
-
}
|
|
2423
|
-
return get$1(profile, matchingSelector);
|
|
2424
|
-
};
|
|
2425
|
-
const MergeTag = ({
|
|
2426
|
-
id
|
|
2427
|
-
}) => {
|
|
2428
|
-
const {
|
|
2429
|
-
loading,
|
|
2430
|
-
profile
|
|
2431
|
-
} = useProfile();
|
|
2432
|
-
if (loading || !profile) {
|
|
2433
|
-
return null;
|
|
2434
|
-
}
|
|
2435
|
-
const value = selectValueFromProfile(profile, id);
|
|
2436
|
-
// DON'T CHANGE
|
|
2437
|
-
return jsx(Fragment, {
|
|
2438
|
-
children: value
|
|
2439
|
-
});
|
|
2440
|
-
};
|
|
2441
|
-
|
|
2442
|
-
export { DefaultExperienceLoadingComponent, ESRLoadingComponent, ESRProvider, Experience, ExperimentsProvider, MergeTag, NinetailedProvider, Personalize, TrackHasSeenComponent, useExperience, useExperiments, useJoinExperiment, useNinetailed, usePersonalize, useProfile };
|
|
2314
|
+
export { DefaultExperienceLoadingComponent, ESRLoadingComponent, ESRProvider, Experience, MergeTag, NinetailedProvider, Personalize, TrackHasSeenComponent, useExperience, useNinetailed, usePersonalize, useProfile };
|
|
@@ -2,6 +2,3 @@ export { Experience, DefaultExperienceLoadingComponent } from './Experience';
|
|
|
2
2
|
export type { ExperienceProps, ExperienceBaseProps, ExperienceComponent, ExperienceLoadingComponent, } from './Experience';
|
|
3
3
|
export { ESRProvider, ESRLoadingComponent } from './ESRLoadingComponent';
|
|
4
4
|
export { useExperience } from './useExperience';
|
|
5
|
-
export { ExperimentsProvider } from './ExperimentsProvider';
|
|
6
|
-
export { useExperiments } from './useExperiments';
|
|
7
|
-
export { useJoinExperiment } from './useJoinExperiment';
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Ninetailed, NinetailedPlugin
|
|
2
|
+
import { Ninetailed, NinetailedPlugin } from '@ninetailed/experience.js';
|
|
3
3
|
import { Profile, Locale, OnErrorHandler, OnLogHandler } from '@ninetailed/experience.js-shared';
|
|
4
|
-
type ExperimentProviderProps = {
|
|
5
|
-
experiments?: ExperienceConfiguration<any>[];
|
|
6
|
-
maximumActiveExperiments?: number;
|
|
7
|
-
};
|
|
8
4
|
export type NinetailedProviderInstantiationProps = {
|
|
9
5
|
clientId: string;
|
|
10
6
|
environment?: string;
|
|
@@ -17,9 +13,8 @@ export type NinetailedProviderInstantiationProps = {
|
|
|
17
13
|
onLog?: OnLogHandler;
|
|
18
14
|
onError?: OnErrorHandler;
|
|
19
15
|
componentViewTrackingThreshold?: number;
|
|
20
|
-
}
|
|
21
|
-
export type NinetailedProviderProps = NinetailedProviderInstantiationProps |
|
|
16
|
+
};
|
|
17
|
+
export type NinetailedProviderProps = NinetailedProviderInstantiationProps | {
|
|
22
18
|
ninetailed: Ninetailed;
|
|
23
|
-
}
|
|
19
|
+
};
|
|
24
20
|
export declare const NinetailedProvider: (props: React.PropsWithChildren<NinetailedProviderProps>) => JSX.Element;
|
|
25
|
-
export {};
|
package/lib/index.d.ts
CHANGED
|
@@ -9,5 +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 {
|
|
12
|
+
export { Experience, ESRProvider, ESRLoadingComponent, DefaultExperienceLoadingComponent, useExperience, } from './Experience';
|
|
13
13
|
export type { ExperienceProps, ExperienceBaseProps, ExperienceComponent, ExperienceLoadingComponent, } from './Experience';
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ninetailed/experience.js-react",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0-beta.0",
|
|
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": "6.
|
|
10
|
+
"@ninetailed/experience.js": "6.3.0-beta.0",
|
|
11
11
|
"react-is": "18.2.0",
|
|
12
|
-
"@ninetailed/experience.js-shared": "6.
|
|
12
|
+
"@ninetailed/experience.js-shared": "6.3.0-beta.0",
|
|
13
13
|
"radash": "10.9.0",
|
|
14
14
|
"react-intersection-observer": "8.34.0"
|
|
15
15
|
},
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
|
-
import { ExperienceConfiguration, Reference } from '@ninetailed/experience.js';
|
|
3
|
-
import { JoinExperiment } from './useProvideJoinExperiment';
|
|
4
|
-
type ExperimentsContextValue<Variant extends Reference> = {
|
|
5
|
-
experiments: ExperienceConfiguration<Variant>[];
|
|
6
|
-
joinExperiment: JoinExperiment;
|
|
7
|
-
};
|
|
8
|
-
export declare const ExperimentsContext: import("react").Context<ExperimentsContextValue<any> | undefined>;
|
|
9
|
-
export {};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import React, { PropsWithChildren } from 'react';
|
|
2
|
-
import { ExperienceConfiguration, Reference } from '@ninetailed/experience.js';
|
|
3
|
-
type ExperimentsProviderProps<Variant extends Reference> = React.PropsWithChildren<{
|
|
4
|
-
experiments: ExperienceConfiguration<Variant>[];
|
|
5
|
-
maximumActiveExperiments?: number;
|
|
6
|
-
}>;
|
|
7
|
-
export declare const ExperimentsProvider: <Variant extends Reference>({ experiments, maximumActiveExperiments, children, }: React.PropsWithChildren<ExperimentsProviderProps<Variant>>) => JSX.Element;
|
|
8
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const useJoinExperiment: () => import("./useProvideJoinExperiment").JoinExperiment;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Profile, ExperienceConfiguration, Reference, VariantRef } from '@ninetailed/experience.js';
|
|
2
|
-
export type JoinExperimentArgs = {
|
|
3
|
-
experiences: ExperienceConfiguration[];
|
|
4
|
-
experiment: ExperienceConfiguration<Reference | VariantRef>;
|
|
5
|
-
profile: Profile;
|
|
6
|
-
};
|
|
7
|
-
export type JoinExperiment = (args: JoinExperimentArgs) => Promise<void>;
|
|
8
|
-
type UseJoinExperimentArgs = {
|
|
9
|
-
experiments: ExperienceConfiguration[];
|
|
10
|
-
maximumActiveExperiments?: number;
|
|
11
|
-
};
|
|
12
|
-
export declare const useProvideJoinExperiment: ({ experiments, maximumActiveExperiments, }: UseJoinExperimentArgs) => (data: JoinExperimentArgs) => Promise<void>;
|
|
13
|
-
export {};
|