@ninetailed/experience.js-react 4.3.0-beta.2 → 4.4.0-beta.1
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 +99 -172
- package/index.js +101 -174
- package/lib/Experience/ExperimentsProvider.d.ts +10 -0
- package/lib/Experience/useExperiments.d.ts +5 -0
- package/lib/Experience/useProvideJoinExperiment.d.ts +7 -1
- package/lib/NinetailedProvider.d.ts +18 -6
- package/lib/index.d.ts +1 -1
- package/lib/useProfile.d.ts +0 -2
- package/package.json +3 -4
- package/lib/Experience/ComponentMarker.d.ts +0 -2
package/index.cjs
CHANGED
|
@@ -5,7 +5,6 @@ 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 reactIntersectionObserver = require('react-intersection-observer');
|
|
10
9
|
var experience_jsShared = require('@ninetailed/experience.js-shared');
|
|
11
10
|
var radash = require('radash');
|
|
@@ -1930,23 +1929,6 @@ const useProfile = () => {
|
|
|
1930
1929
|
});
|
|
1931
1930
|
};
|
|
1932
1931
|
|
|
1933
|
-
const ExperimentsContext = /*#__PURE__*/React.createContext(undefined);
|
|
1934
|
-
|
|
1935
|
-
const useExperimentsContext = () => {
|
|
1936
|
-
const context = React.useContext(ExperimentsContext);
|
|
1937
|
-
if (context === undefined) {
|
|
1938
|
-
throw new Error('The component using the the context must be a descendant of the ExperimentsProvider');
|
|
1939
|
-
}
|
|
1940
|
-
return context;
|
|
1941
|
-
};
|
|
1942
|
-
|
|
1943
|
-
const useExperiments = () => {
|
|
1944
|
-
const context = useExperimentsContext();
|
|
1945
|
-
return {
|
|
1946
|
-
experiments: context.experiments
|
|
1947
|
-
};
|
|
1948
|
-
};
|
|
1949
|
-
|
|
1950
1932
|
const useExperienceSelectionMiddleware = ({
|
|
1951
1933
|
experiences,
|
|
1952
1934
|
baseline,
|
|
@@ -1981,9 +1963,6 @@ const useExperience = ({
|
|
|
1981
1963
|
experiences
|
|
1982
1964
|
}) => {
|
|
1983
1965
|
const profileState = useProfile();
|
|
1984
|
-
const {
|
|
1985
|
-
experiments
|
|
1986
|
-
} = useExperiments();
|
|
1987
1966
|
const hasVariants = experiences.map(experience => experience_js.selectHasExperienceVariants(experience, baseline)).reduce((acc, curr) => acc || curr, false);
|
|
1988
1967
|
const {
|
|
1989
1968
|
status,
|
|
@@ -2040,7 +2019,7 @@ const useExperience = ({
|
|
|
2040
2019
|
// @ts-ignore
|
|
2041
2020
|
return overrideResult(emptyReturn);
|
|
2042
2021
|
}
|
|
2043
|
-
const activeExperiments = experience_js.selectActiveExperiments(
|
|
2022
|
+
const activeExperiments = experience_js.selectActiveExperiments(experiences, profile);
|
|
2044
2023
|
const experience = experience_js.selectExperience({
|
|
2045
2024
|
experiences,
|
|
2046
2025
|
activeExperiments,
|
|
@@ -2083,41 +2062,21 @@ const useExperience = ({
|
|
|
2083
2062
|
}));
|
|
2084
2063
|
};
|
|
2085
2064
|
|
|
2065
|
+
const ExperimentsContext = /*#__PURE__*/React.createContext(undefined);
|
|
2066
|
+
|
|
2067
|
+
const useExperimentsContext = () => {
|
|
2068
|
+
const context = React.useContext(ExperimentsContext);
|
|
2069
|
+
if (context === undefined) {
|
|
2070
|
+
throw new Error('The component using the the context must be a descendant of the ExperimentsProvider');
|
|
2071
|
+
}
|
|
2072
|
+
return context;
|
|
2073
|
+
};
|
|
2074
|
+
|
|
2086
2075
|
const useJoinExperiment = () => {
|
|
2087
2076
|
const context = useExperimentsContext();
|
|
2088
2077
|
return context.joinExperiment;
|
|
2089
2078
|
};
|
|
2090
2079
|
|
|
2091
|
-
const ComponentMarker = /*#__PURE__*/React.forwardRef((_, ref) => {
|
|
2092
|
-
const {
|
|
2093
|
-
logger
|
|
2094
|
-
} = useNinetailed();
|
|
2095
|
-
const markerRef = React.useRef(null);
|
|
2096
|
-
React.useEffect(() => {
|
|
2097
|
-
// TODO: Create a better message
|
|
2098
|
-
logger.debug('Using fallback mechanism to select component.');
|
|
2099
|
-
}, [logger]);
|
|
2100
|
-
React.useEffect(() => {
|
|
2101
|
-
if (markerRef.current) {
|
|
2102
|
-
const nextSibling = markerRef.current.nextSibling;
|
|
2103
|
-
if (ref) {
|
|
2104
|
-
if (typeof ref === 'function') {
|
|
2105
|
-
ref(nextSibling);
|
|
2106
|
-
} else {
|
|
2107
|
-
ref.current = nextSibling;
|
|
2108
|
-
}
|
|
2109
|
-
}
|
|
2110
|
-
}
|
|
2111
|
-
}, []);
|
|
2112
|
-
return jsxRuntime.jsx("div", {
|
|
2113
|
-
className: "nt-cmp-marker",
|
|
2114
|
-
style: {
|
|
2115
|
-
display: 'none !important'
|
|
2116
|
-
},
|
|
2117
|
-
ref: markerRef
|
|
2118
|
-
});
|
|
2119
|
-
});
|
|
2120
|
-
|
|
2121
2080
|
const DefaultExperienceLoadingComponent = _a => {
|
|
2122
2081
|
var {
|
|
2123
2082
|
component: Component,
|
|
@@ -2171,10 +2130,6 @@ const Experience = _a => {
|
|
|
2171
2130
|
passthroughProps
|
|
2172
2131
|
} = _a,
|
|
2173
2132
|
baseline = __rest(_a, ["experiences", "component", "loadingComponent", "passthroughProps"]);
|
|
2174
|
-
const {
|
|
2175
|
-
observeElement,
|
|
2176
|
-
unobserveElement
|
|
2177
|
-
} = useNinetailed();
|
|
2178
2133
|
// TODO we actually could hook into the experience hook here with the plugins
|
|
2179
2134
|
const {
|
|
2180
2135
|
status,
|
|
@@ -2189,46 +2144,22 @@ const Experience = _a => {
|
|
|
2189
2144
|
experiences
|
|
2190
2145
|
});
|
|
2191
2146
|
const joinExperiment = useJoinExperiment();
|
|
2192
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2193
|
-
// @ts-ignore
|
|
2194
|
-
const isComponentForwardRef = reactIs.isForwardRef(jsxRuntime.jsx(Component, {}));
|
|
2195
|
-
const componentRef = React.useRef(null);
|
|
2196
2147
|
React.useEffect(() => {
|
|
2197
|
-
if (status === 'success' && experience && profile) {
|
|
2148
|
+
if (status === 'success' && experience && experience.type === 'nt_experiment' && variant && profile) {
|
|
2198
2149
|
joinExperiment({
|
|
2199
2150
|
experiences,
|
|
2200
2151
|
experiment: experience,
|
|
2152
|
+
variant: Object.assign(Object.assign({}, variant), {
|
|
2153
|
+
hidden: 'hidden' in variant ? variant.hidden : false
|
|
2154
|
+
}),
|
|
2201
2155
|
profile
|
|
2202
2156
|
});
|
|
2203
2157
|
}
|
|
2204
|
-
}, [status, experience, profile]);
|
|
2205
|
-
React.useEffect(() => {
|
|
2206
|
-
const componentElement = componentRef.current;
|
|
2207
|
-
if (componentElement) {
|
|
2208
|
-
observeElement({
|
|
2209
|
-
element: componentElement,
|
|
2210
|
-
experienceId: experience === null || experience === void 0 ? void 0 : experience.id,
|
|
2211
|
-
variantId: variant === null || variant === void 0 ? void 0 : variant.id,
|
|
2212
|
-
baselineId: baseline.id,
|
|
2213
|
-
audienceId: audience === null || audience === void 0 ? void 0 : audience.id
|
|
2214
|
-
});
|
|
2215
|
-
}
|
|
2216
|
-
return () => {
|
|
2217
|
-
if (componentElement) {
|
|
2218
|
-
unobserveElement(componentElement);
|
|
2219
|
-
}
|
|
2220
|
-
};
|
|
2221
|
-
}, [observeElement, unobserveElement, experience, baseline, variant, audience]);
|
|
2158
|
+
}, [status, experience, variant, profile]);
|
|
2222
2159
|
if (!hasVariants) {
|
|
2223
|
-
return
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
}), /*#__PURE__*/React.createElement(Component, Object.assign({}, passthroughProps, baseline, {
|
|
2227
|
-
key: baseline.id
|
|
2228
|
-
}, isComponentForwardRef ? {
|
|
2229
|
-
ref: componentRef
|
|
2230
|
-
} : {}))]
|
|
2231
|
-
});
|
|
2160
|
+
return /*#__PURE__*/React.createElement(Component, Object.assign({}, passthroughProps, baseline, {
|
|
2161
|
+
key: baseline.id
|
|
2162
|
+
}));
|
|
2232
2163
|
}
|
|
2233
2164
|
if (status === 'loading') {
|
|
2234
2165
|
return /*#__PURE__*/React.createElement(LoadingComponent, Object.assign({}, baseline, {
|
|
@@ -2239,20 +2170,14 @@ const Experience = _a => {
|
|
|
2239
2170
|
}));
|
|
2240
2171
|
}
|
|
2241
2172
|
if (!experience) {
|
|
2242
|
-
return jsxRuntime.
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
isPersonalized: false,
|
|
2248
|
-
audience: {
|
|
2249
|
-
id: 'baseline'
|
|
2250
|
-
}
|
|
2173
|
+
return jsxRuntime.jsx(Component, Object.assign({}, passthroughProps, baseline, {
|
|
2174
|
+
ninetailed: {
|
|
2175
|
+
isPersonalized: false,
|
|
2176
|
+
audience: {
|
|
2177
|
+
id: 'baseline'
|
|
2251
2178
|
}
|
|
2252
|
-
}
|
|
2253
|
-
|
|
2254
|
-
} : {}))]
|
|
2255
|
-
});
|
|
2179
|
+
}
|
|
2180
|
+
}));
|
|
2256
2181
|
}
|
|
2257
2182
|
if (!variant) {
|
|
2258
2183
|
return jsxRuntime.jsx(TrackExperience, Object.assign({
|
|
@@ -2261,20 +2186,14 @@ const Experience = _a => {
|
|
|
2261
2186
|
// the profile is definitely defined, otherwise there wouldn't be an experience selected
|
|
2262
2187
|
profile: profile
|
|
2263
2188
|
}, {
|
|
2264
|
-
children: jsxRuntime.
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
isPersonalized: false,
|
|
2270
|
-
audience: {
|
|
2271
|
-
id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'all visitors'
|
|
2272
|
-
}
|
|
2189
|
+
children: jsxRuntime.jsx(Component, Object.assign({}, passthroughProps, baseline, {
|
|
2190
|
+
ninetailed: {
|
|
2191
|
+
isPersonalized: false,
|
|
2192
|
+
audience: {
|
|
2193
|
+
id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'all visitors'
|
|
2273
2194
|
}
|
|
2274
|
-
}
|
|
2275
|
-
|
|
2276
|
-
} : {}))]
|
|
2277
|
-
})
|
|
2195
|
+
}
|
|
2196
|
+
}))
|
|
2278
2197
|
}), baseline.id);
|
|
2279
2198
|
}
|
|
2280
2199
|
const isVariantHidden = 'hidden' in variant && variant.hidden;
|
|
@@ -2284,21 +2203,15 @@ const Experience = _a => {
|
|
|
2284
2203
|
// the profile is definitely defined, otherwise there wouldn't be an experience selected
|
|
2285
2204
|
profile: profile
|
|
2286
2205
|
}, {
|
|
2287
|
-
children: !isVariantHidden ?
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
isPersonalized,
|
|
2294
|
-
audience: {
|
|
2295
|
-
id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'all visitors'
|
|
2296
|
-
}
|
|
2206
|
+
children: !isVariantHidden ? /*#__PURE__*/React.createElement(Component, Object.assign({}, Object.assign(Object.assign({}, passthroughProps), variant), {
|
|
2207
|
+
key: `${experience.id}-${variant.id}`,
|
|
2208
|
+
ninetailed: {
|
|
2209
|
+
isPersonalized,
|
|
2210
|
+
audience: {
|
|
2211
|
+
id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'all visitors'
|
|
2297
2212
|
}
|
|
2298
|
-
}
|
|
2299
|
-
|
|
2300
|
-
} : {}))]
|
|
2301
|
-
}) : null
|
|
2213
|
+
}
|
|
2214
|
+
})) : null
|
|
2302
2215
|
}));
|
|
2303
2216
|
};
|
|
2304
2217
|
|
|
@@ -2402,15 +2315,13 @@ const debounce = (fn, wait) => {
|
|
|
2402
2315
|
debouncedFn();
|
|
2403
2316
|
};
|
|
2404
2317
|
};
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
maximumActiveExperiments: _maximumActiveExperiments = 1
|
|
2408
|
-
}) => {
|
|
2318
|
+
// TODO: the majority of this code should be moved to the experience.js javascript package
|
|
2319
|
+
const useProvideJoinExperiment = _ => {
|
|
2409
2320
|
const {
|
|
2410
2321
|
identify
|
|
2411
2322
|
} = useNinetailed();
|
|
2412
2323
|
const joinExperimentIdentify = debounce(args => {
|
|
2413
|
-
const traits = args.
|
|
2324
|
+
const traits = args.reduce((traits, [experimentJoinTraits]) => {
|
|
2414
2325
|
return Object.assign(Object.assign({}, experimentJoinTraits), traits);
|
|
2415
2326
|
}, {});
|
|
2416
2327
|
identify('', traits);
|
|
@@ -2418,6 +2329,7 @@ const useProvideJoinExperiment = ({
|
|
|
2418
2329
|
return React.useCallback(data => __awaiter(void 0, void 0, void 0, function* () {
|
|
2419
2330
|
const {
|
|
2420
2331
|
experiment,
|
|
2332
|
+
variant,
|
|
2421
2333
|
profile
|
|
2422
2334
|
} = data;
|
|
2423
2335
|
const isExperiment = experiment.type === 'nt_experiment';
|
|
@@ -2425,17 +2337,17 @@ const useProvideJoinExperiment = ({
|
|
|
2425
2337
|
experience_jsShared.logger.warn(`The experience ${experiment.id}, which you tried to join, is not an experiment.`);
|
|
2426
2338
|
return;
|
|
2427
2339
|
}
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
experience_jsShared.logger.warn(`The maximum number of active experiments (${_maximumActiveExperiments}) has been reached.`);
|
|
2340
|
+
if (!experience_jsShared.isExperienceSticky(experiment)) {
|
|
2341
|
+
experience_jsShared.logger.debug("Won't add experiment to traits, as it's not sticky.");
|
|
2431
2342
|
return;
|
|
2432
2343
|
}
|
|
2433
|
-
|
|
2344
|
+
const activeExperimentIds = experience_jsShared.selectActiveExperimentIds(profile);
|
|
2345
|
+
if (activeExperimentIds.some(activeExperimentId => activeExperimentId === experiment.id)) {
|
|
2434
2346
|
experience_jsShared.logger.debug(`The user is already part of experiment ${experiment.id}. Won't join again.`);
|
|
2435
2347
|
return;
|
|
2436
2348
|
}
|
|
2437
2349
|
joinExperimentIdentify({
|
|
2438
|
-
[`${EXPERIENCE_TRAIT_PREFIX}${experiment.id}`]:
|
|
2350
|
+
[`${EXPERIENCE_TRAIT_PREFIX}${experiment.id}`]: variant.hidden ? 'hidden' : variant.id
|
|
2439
2351
|
});
|
|
2440
2352
|
experience_jsShared.logger.debug(`Sent event to join experiment ${experiment.id}.`);
|
|
2441
2353
|
}), []);
|
|
@@ -2446,10 +2358,7 @@ const ExperimentsProvider = ({
|
|
|
2446
2358
|
maximumActiveExperiments: _maximumActiveExperiments = 1,
|
|
2447
2359
|
children
|
|
2448
2360
|
}) => {
|
|
2449
|
-
const joinExperiment = useProvideJoinExperiment(
|
|
2450
|
-
experiments,
|
|
2451
|
-
maximumActiveExperiments: _maximumActiveExperiments
|
|
2452
|
-
});
|
|
2361
|
+
const joinExperiment = useProvideJoinExperiment();
|
|
2453
2362
|
return jsxRuntime.jsx(ExperimentsContext.Provider, Object.assign({
|
|
2454
2363
|
value: {
|
|
2455
2364
|
experiments,
|
|
@@ -2460,40 +2369,58 @@ const ExperimentsProvider = ({
|
|
|
2460
2369
|
}));
|
|
2461
2370
|
};
|
|
2462
2371
|
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2372
|
+
/**
|
|
2373
|
+
* @deprecated
|
|
2374
|
+
*
|
|
2375
|
+
* This will get removed in v5 of the SDK.
|
|
2376
|
+
*/
|
|
2377
|
+
const useExperiments = () => {
|
|
2378
|
+
const context = useExperimentsContext();
|
|
2379
|
+
return {
|
|
2380
|
+
experiments: context.experiments
|
|
2381
|
+
};
|
|
2382
|
+
};
|
|
2383
|
+
|
|
2384
|
+
const NinetailedProvider = props => {
|
|
2385
|
+
const ninetailed = React.useMemo(() => {
|
|
2386
|
+
if ('ninetailed' in props) {
|
|
2387
|
+
return props.ninetailed;
|
|
2388
|
+
}
|
|
2389
|
+
const {
|
|
2390
|
+
clientId,
|
|
2391
|
+
environment,
|
|
2392
|
+
preview,
|
|
2393
|
+
url,
|
|
2394
|
+
profile,
|
|
2395
|
+
locale,
|
|
2396
|
+
requestTimeout,
|
|
2397
|
+
plugins = [],
|
|
2398
|
+
onLog,
|
|
2399
|
+
onError
|
|
2400
|
+
} = props;
|
|
2401
|
+
return new experience_js.Ninetailed({
|
|
2402
|
+
clientId,
|
|
2403
|
+
environment,
|
|
2404
|
+
preview
|
|
2405
|
+
}, {
|
|
2406
|
+
url,
|
|
2407
|
+
plugins,
|
|
2408
|
+
profile,
|
|
2409
|
+
locale,
|
|
2410
|
+
requestTimeout,
|
|
2411
|
+
onLog,
|
|
2412
|
+
onError
|
|
2413
|
+
});
|
|
2414
|
+
}, []);
|
|
2415
|
+
const {
|
|
2416
|
+
children
|
|
2417
|
+
} = props;
|
|
2491
2418
|
return jsxRuntime.jsx(NinetailedContext.Provider, Object.assign({
|
|
2492
2419
|
value: ninetailed
|
|
2493
2420
|
}, {
|
|
2494
2421
|
children: jsxRuntime.jsx(ExperimentsProvider, Object.assign({
|
|
2495
|
-
experiments:
|
|
2496
|
-
maximumActiveExperiments:
|
|
2422
|
+
experiments: [],
|
|
2423
|
+
maximumActiveExperiments: 10000
|
|
2497
2424
|
}, {
|
|
2498
2425
|
children: children
|
|
2499
2426
|
}))
|
package/index.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import React, { createContext, useContext, useEffect, useState, useRef, useMemo,
|
|
2
|
+
import React, { createContext, useContext, useEffect, useState, useRef, useMemo, createElement as createElement$1, useCallback } from 'react';
|
|
3
3
|
import { selectDistribution, makeExperienceSelectMiddleware, selectHasExperienceVariants, selectActiveExperiments, selectExperience, selectExperienceVariant, Ninetailed, selectVariant } from '@ninetailed/experience.js';
|
|
4
|
-
import { isForwardRef } from 'react-is';
|
|
5
4
|
import { useInView } from 'react-intersection-observer';
|
|
6
|
-
import { isBrowser, logger } from '@ninetailed/experience.js-shared';
|
|
5
|
+
import { isBrowser, logger, isExperienceSticky, selectActiveExperimentIds } from '@ninetailed/experience.js-shared';
|
|
7
6
|
import { isEqual, debounce as debounce$1, get as get$1 } from 'radash';
|
|
8
7
|
|
|
9
8
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
@@ -1922,23 +1921,6 @@ const useProfile = () => {
|
|
|
1922
1921
|
});
|
|
1923
1922
|
};
|
|
1924
1923
|
|
|
1925
|
-
const ExperimentsContext = /*#__PURE__*/createContext(undefined);
|
|
1926
|
-
|
|
1927
|
-
const useExperimentsContext = () => {
|
|
1928
|
-
const context = useContext(ExperimentsContext);
|
|
1929
|
-
if (context === undefined) {
|
|
1930
|
-
throw new Error('The component using the the context must be a descendant of the ExperimentsProvider');
|
|
1931
|
-
}
|
|
1932
|
-
return context;
|
|
1933
|
-
};
|
|
1934
|
-
|
|
1935
|
-
const useExperiments = () => {
|
|
1936
|
-
const context = useExperimentsContext();
|
|
1937
|
-
return {
|
|
1938
|
-
experiments: context.experiments
|
|
1939
|
-
};
|
|
1940
|
-
};
|
|
1941
|
-
|
|
1942
1924
|
const useExperienceSelectionMiddleware = ({
|
|
1943
1925
|
experiences,
|
|
1944
1926
|
baseline,
|
|
@@ -1973,9 +1955,6 @@ const useExperience = ({
|
|
|
1973
1955
|
experiences
|
|
1974
1956
|
}) => {
|
|
1975
1957
|
const profileState = useProfile();
|
|
1976
|
-
const {
|
|
1977
|
-
experiments
|
|
1978
|
-
} = useExperiments();
|
|
1979
1958
|
const hasVariants = experiences.map(experience => selectHasExperienceVariants(experience, baseline)).reduce((acc, curr) => acc || curr, false);
|
|
1980
1959
|
const {
|
|
1981
1960
|
status,
|
|
@@ -2032,7 +2011,7 @@ const useExperience = ({
|
|
|
2032
2011
|
// @ts-ignore
|
|
2033
2012
|
return overrideResult(emptyReturn);
|
|
2034
2013
|
}
|
|
2035
|
-
const activeExperiments = selectActiveExperiments(
|
|
2014
|
+
const activeExperiments = selectActiveExperiments(experiences, profile);
|
|
2036
2015
|
const experience = selectExperience({
|
|
2037
2016
|
experiences,
|
|
2038
2017
|
activeExperiments,
|
|
@@ -2075,41 +2054,21 @@ const useExperience = ({
|
|
|
2075
2054
|
}));
|
|
2076
2055
|
};
|
|
2077
2056
|
|
|
2057
|
+
const ExperimentsContext = /*#__PURE__*/createContext(undefined);
|
|
2058
|
+
|
|
2059
|
+
const useExperimentsContext = () => {
|
|
2060
|
+
const context = useContext(ExperimentsContext);
|
|
2061
|
+
if (context === undefined) {
|
|
2062
|
+
throw new Error('The component using the the context must be a descendant of the ExperimentsProvider');
|
|
2063
|
+
}
|
|
2064
|
+
return context;
|
|
2065
|
+
};
|
|
2066
|
+
|
|
2078
2067
|
const useJoinExperiment = () => {
|
|
2079
2068
|
const context = useExperimentsContext();
|
|
2080
2069
|
return context.joinExperiment;
|
|
2081
2070
|
};
|
|
2082
2071
|
|
|
2083
|
-
const ComponentMarker = /*#__PURE__*/forwardRef((_, ref) => {
|
|
2084
|
-
const {
|
|
2085
|
-
logger
|
|
2086
|
-
} = useNinetailed();
|
|
2087
|
-
const markerRef = useRef(null);
|
|
2088
|
-
useEffect(() => {
|
|
2089
|
-
// TODO: Create a better message
|
|
2090
|
-
logger.debug('Using fallback mechanism to select component.');
|
|
2091
|
-
}, [logger]);
|
|
2092
|
-
useEffect(() => {
|
|
2093
|
-
if (markerRef.current) {
|
|
2094
|
-
const nextSibling = markerRef.current.nextSibling;
|
|
2095
|
-
if (ref) {
|
|
2096
|
-
if (typeof ref === 'function') {
|
|
2097
|
-
ref(nextSibling);
|
|
2098
|
-
} else {
|
|
2099
|
-
ref.current = nextSibling;
|
|
2100
|
-
}
|
|
2101
|
-
}
|
|
2102
|
-
}
|
|
2103
|
-
}, []);
|
|
2104
|
-
return jsx("div", {
|
|
2105
|
-
className: "nt-cmp-marker",
|
|
2106
|
-
style: {
|
|
2107
|
-
display: 'none !important'
|
|
2108
|
-
},
|
|
2109
|
-
ref: markerRef
|
|
2110
|
-
});
|
|
2111
|
-
});
|
|
2112
|
-
|
|
2113
2072
|
const DefaultExperienceLoadingComponent = _a => {
|
|
2114
2073
|
var {
|
|
2115
2074
|
component: Component,
|
|
@@ -2163,10 +2122,6 @@ const Experience = _a => {
|
|
|
2163
2122
|
passthroughProps
|
|
2164
2123
|
} = _a,
|
|
2165
2124
|
baseline = __rest(_a, ["experiences", "component", "loadingComponent", "passthroughProps"]);
|
|
2166
|
-
const {
|
|
2167
|
-
observeElement,
|
|
2168
|
-
unobserveElement
|
|
2169
|
-
} = useNinetailed();
|
|
2170
2125
|
// TODO we actually could hook into the experience hook here with the plugins
|
|
2171
2126
|
const {
|
|
2172
2127
|
status,
|
|
@@ -2181,46 +2136,22 @@ const Experience = _a => {
|
|
|
2181
2136
|
experiences
|
|
2182
2137
|
});
|
|
2183
2138
|
const joinExperiment = useJoinExperiment();
|
|
2184
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2185
|
-
// @ts-ignore
|
|
2186
|
-
const isComponentForwardRef = isForwardRef(jsx(Component, {}));
|
|
2187
|
-
const componentRef = useRef(null);
|
|
2188
2139
|
useEffect(() => {
|
|
2189
|
-
if (status === 'success' && experience && profile) {
|
|
2140
|
+
if (status === 'success' && experience && experience.type === 'nt_experiment' && variant && profile) {
|
|
2190
2141
|
joinExperiment({
|
|
2191
2142
|
experiences,
|
|
2192
2143
|
experiment: experience,
|
|
2144
|
+
variant: Object.assign(Object.assign({}, variant), {
|
|
2145
|
+
hidden: 'hidden' in variant ? variant.hidden : false
|
|
2146
|
+
}),
|
|
2193
2147
|
profile
|
|
2194
2148
|
});
|
|
2195
2149
|
}
|
|
2196
|
-
}, [status, experience, profile]);
|
|
2197
|
-
useEffect(() => {
|
|
2198
|
-
const componentElement = componentRef.current;
|
|
2199
|
-
if (componentElement) {
|
|
2200
|
-
observeElement({
|
|
2201
|
-
element: componentElement,
|
|
2202
|
-
experienceId: experience === null || experience === void 0 ? void 0 : experience.id,
|
|
2203
|
-
variantId: variant === null || variant === void 0 ? void 0 : variant.id,
|
|
2204
|
-
baselineId: baseline.id,
|
|
2205
|
-
audienceId: audience === null || audience === void 0 ? void 0 : audience.id
|
|
2206
|
-
});
|
|
2207
|
-
}
|
|
2208
|
-
return () => {
|
|
2209
|
-
if (componentElement) {
|
|
2210
|
-
unobserveElement(componentElement);
|
|
2211
|
-
}
|
|
2212
|
-
};
|
|
2213
|
-
}, [observeElement, unobserveElement, experience, baseline, variant, audience]);
|
|
2150
|
+
}, [status, experience, variant, profile]);
|
|
2214
2151
|
if (!hasVariants) {
|
|
2215
|
-
return
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
}), /*#__PURE__*/createElement$1(Component, Object.assign({}, passthroughProps, baseline, {
|
|
2219
|
-
key: baseline.id
|
|
2220
|
-
}, isComponentForwardRef ? {
|
|
2221
|
-
ref: componentRef
|
|
2222
|
-
} : {}))]
|
|
2223
|
-
});
|
|
2152
|
+
return /*#__PURE__*/createElement$1(Component, Object.assign({}, passthroughProps, baseline, {
|
|
2153
|
+
key: baseline.id
|
|
2154
|
+
}));
|
|
2224
2155
|
}
|
|
2225
2156
|
if (status === 'loading') {
|
|
2226
2157
|
return /*#__PURE__*/createElement$1(LoadingComponent, Object.assign({}, baseline, {
|
|
@@ -2231,20 +2162,14 @@ const Experience = _a => {
|
|
|
2231
2162
|
}));
|
|
2232
2163
|
}
|
|
2233
2164
|
if (!experience) {
|
|
2234
|
-
return
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
isPersonalized: false,
|
|
2240
|
-
audience: {
|
|
2241
|
-
id: 'baseline'
|
|
2242
|
-
}
|
|
2165
|
+
return jsx(Component, Object.assign({}, passthroughProps, baseline, {
|
|
2166
|
+
ninetailed: {
|
|
2167
|
+
isPersonalized: false,
|
|
2168
|
+
audience: {
|
|
2169
|
+
id: 'baseline'
|
|
2243
2170
|
}
|
|
2244
|
-
}
|
|
2245
|
-
|
|
2246
|
-
} : {}))]
|
|
2247
|
-
});
|
|
2171
|
+
}
|
|
2172
|
+
}));
|
|
2248
2173
|
}
|
|
2249
2174
|
if (!variant) {
|
|
2250
2175
|
return jsx(TrackExperience, Object.assign({
|
|
@@ -2253,20 +2178,14 @@ const Experience = _a => {
|
|
|
2253
2178
|
// the profile is definitely defined, otherwise there wouldn't be an experience selected
|
|
2254
2179
|
profile: profile
|
|
2255
2180
|
}, {
|
|
2256
|
-
children:
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
isPersonalized: false,
|
|
2262
|
-
audience: {
|
|
2263
|
-
id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'all visitors'
|
|
2264
|
-
}
|
|
2181
|
+
children: jsx(Component, Object.assign({}, passthroughProps, baseline, {
|
|
2182
|
+
ninetailed: {
|
|
2183
|
+
isPersonalized: false,
|
|
2184
|
+
audience: {
|
|
2185
|
+
id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'all visitors'
|
|
2265
2186
|
}
|
|
2266
|
-
}
|
|
2267
|
-
|
|
2268
|
-
} : {}))]
|
|
2269
|
-
})
|
|
2187
|
+
}
|
|
2188
|
+
}))
|
|
2270
2189
|
}), baseline.id);
|
|
2271
2190
|
}
|
|
2272
2191
|
const isVariantHidden = 'hidden' in variant && variant.hidden;
|
|
@@ -2276,21 +2195,15 @@ const Experience = _a => {
|
|
|
2276
2195
|
// the profile is definitely defined, otherwise there wouldn't be an experience selected
|
|
2277
2196
|
profile: profile
|
|
2278
2197
|
}, {
|
|
2279
|
-
children: !isVariantHidden ?
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
isPersonalized,
|
|
2286
|
-
audience: {
|
|
2287
|
-
id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'all visitors'
|
|
2288
|
-
}
|
|
2198
|
+
children: !isVariantHidden ? /*#__PURE__*/createElement$1(Component, Object.assign({}, Object.assign(Object.assign({}, passthroughProps), variant), {
|
|
2199
|
+
key: `${experience.id}-${variant.id}`,
|
|
2200
|
+
ninetailed: {
|
|
2201
|
+
isPersonalized,
|
|
2202
|
+
audience: {
|
|
2203
|
+
id: (audience === null || audience === void 0 ? void 0 : audience.id) || 'all visitors'
|
|
2289
2204
|
}
|
|
2290
|
-
}
|
|
2291
|
-
|
|
2292
|
-
} : {}))]
|
|
2293
|
-
}) : null
|
|
2205
|
+
}
|
|
2206
|
+
})) : null
|
|
2294
2207
|
}));
|
|
2295
2208
|
};
|
|
2296
2209
|
|
|
@@ -2394,15 +2307,13 @@ const debounce = (fn, wait) => {
|
|
|
2394
2307
|
debouncedFn();
|
|
2395
2308
|
};
|
|
2396
2309
|
};
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
maximumActiveExperiments: _maximumActiveExperiments = 1
|
|
2400
|
-
}) => {
|
|
2310
|
+
// TODO: the majority of this code should be moved to the experience.js javascript package
|
|
2311
|
+
const useProvideJoinExperiment = _ => {
|
|
2401
2312
|
const {
|
|
2402
2313
|
identify
|
|
2403
2314
|
} = useNinetailed();
|
|
2404
2315
|
const joinExperimentIdentify = debounce(args => {
|
|
2405
|
-
const traits = args.
|
|
2316
|
+
const traits = args.reduce((traits, [experimentJoinTraits]) => {
|
|
2406
2317
|
return Object.assign(Object.assign({}, experimentJoinTraits), traits);
|
|
2407
2318
|
}, {});
|
|
2408
2319
|
identify('', traits);
|
|
@@ -2410,6 +2321,7 @@ const useProvideJoinExperiment = ({
|
|
|
2410
2321
|
return useCallback(data => __awaiter(void 0, void 0, void 0, function* () {
|
|
2411
2322
|
const {
|
|
2412
2323
|
experiment,
|
|
2324
|
+
variant,
|
|
2413
2325
|
profile
|
|
2414
2326
|
} = data;
|
|
2415
2327
|
const isExperiment = experiment.type === 'nt_experiment';
|
|
@@ -2417,17 +2329,17 @@ const useProvideJoinExperiment = ({
|
|
|
2417
2329
|
logger.warn(`The experience ${experiment.id}, which you tried to join, is not an experiment.`);
|
|
2418
2330
|
return;
|
|
2419
2331
|
}
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
logger.warn(`The maximum number of active experiments (${_maximumActiveExperiments}) has been reached.`);
|
|
2332
|
+
if (!isExperienceSticky(experiment)) {
|
|
2333
|
+
logger.debug("Won't add experiment to traits, as it's not sticky.");
|
|
2423
2334
|
return;
|
|
2424
2335
|
}
|
|
2425
|
-
|
|
2336
|
+
const activeExperimentIds = selectActiveExperimentIds(profile);
|
|
2337
|
+
if (activeExperimentIds.some(activeExperimentId => activeExperimentId === experiment.id)) {
|
|
2426
2338
|
logger.debug(`The user is already part of experiment ${experiment.id}. Won't join again.`);
|
|
2427
2339
|
return;
|
|
2428
2340
|
}
|
|
2429
2341
|
joinExperimentIdentify({
|
|
2430
|
-
[`${EXPERIENCE_TRAIT_PREFIX}${experiment.id}`]:
|
|
2342
|
+
[`${EXPERIENCE_TRAIT_PREFIX}${experiment.id}`]: variant.hidden ? 'hidden' : variant.id
|
|
2431
2343
|
});
|
|
2432
2344
|
logger.debug(`Sent event to join experiment ${experiment.id}.`);
|
|
2433
2345
|
}), []);
|
|
@@ -2438,10 +2350,7 @@ const ExperimentsProvider = ({
|
|
|
2438
2350
|
maximumActiveExperiments: _maximumActiveExperiments = 1,
|
|
2439
2351
|
children
|
|
2440
2352
|
}) => {
|
|
2441
|
-
const joinExperiment = useProvideJoinExperiment(
|
|
2442
|
-
experiments,
|
|
2443
|
-
maximumActiveExperiments: _maximumActiveExperiments
|
|
2444
|
-
});
|
|
2353
|
+
const joinExperiment = useProvideJoinExperiment();
|
|
2445
2354
|
return jsx(ExperimentsContext.Provider, Object.assign({
|
|
2446
2355
|
value: {
|
|
2447
2356
|
experiments,
|
|
@@ -2452,40 +2361,58 @@ const ExperimentsProvider = ({
|
|
|
2452
2361
|
}));
|
|
2453
2362
|
};
|
|
2454
2363
|
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2364
|
+
/**
|
|
2365
|
+
* @deprecated
|
|
2366
|
+
*
|
|
2367
|
+
* This will get removed in v5 of the SDK.
|
|
2368
|
+
*/
|
|
2369
|
+
const useExperiments = () => {
|
|
2370
|
+
const context = useExperimentsContext();
|
|
2371
|
+
return {
|
|
2372
|
+
experiments: context.experiments
|
|
2373
|
+
};
|
|
2374
|
+
};
|
|
2375
|
+
|
|
2376
|
+
const NinetailedProvider = props => {
|
|
2377
|
+
const ninetailed = useMemo(() => {
|
|
2378
|
+
if ('ninetailed' in props) {
|
|
2379
|
+
return props.ninetailed;
|
|
2380
|
+
}
|
|
2381
|
+
const {
|
|
2382
|
+
clientId,
|
|
2383
|
+
environment,
|
|
2384
|
+
preview,
|
|
2385
|
+
url,
|
|
2386
|
+
profile,
|
|
2387
|
+
locale,
|
|
2388
|
+
requestTimeout,
|
|
2389
|
+
plugins = [],
|
|
2390
|
+
onLog,
|
|
2391
|
+
onError
|
|
2392
|
+
} = props;
|
|
2393
|
+
return new Ninetailed({
|
|
2394
|
+
clientId,
|
|
2395
|
+
environment,
|
|
2396
|
+
preview
|
|
2397
|
+
}, {
|
|
2398
|
+
url,
|
|
2399
|
+
plugins,
|
|
2400
|
+
profile,
|
|
2401
|
+
locale,
|
|
2402
|
+
requestTimeout,
|
|
2403
|
+
onLog,
|
|
2404
|
+
onError
|
|
2405
|
+
});
|
|
2406
|
+
}, []);
|
|
2407
|
+
const {
|
|
2408
|
+
children
|
|
2409
|
+
} = props;
|
|
2483
2410
|
return jsx(NinetailedContext.Provider, Object.assign({
|
|
2484
2411
|
value: ninetailed
|
|
2485
2412
|
}, {
|
|
2486
2413
|
children: jsx(ExperimentsProvider, Object.assign({
|
|
2487
|
-
experiments:
|
|
2488
|
-
maximumActiveExperiments:
|
|
2414
|
+
experiments: [],
|
|
2415
|
+
maximumActiveExperiments: 10000
|
|
2489
2416
|
}, {
|
|
2490
2417
|
children: children
|
|
2491
2418
|
}))
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from 'react';
|
|
2
2
|
import { ExperienceConfiguration, Reference } from '@ninetailed/experience.js';
|
|
3
3
|
type ExperimentsProviderProps<Variant extends Reference> = React.PropsWithChildren<{
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated
|
|
6
|
+
*
|
|
7
|
+
* This will get removed in v5
|
|
8
|
+
*/
|
|
4
9
|
experiments: ExperienceConfiguration<Variant>[];
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated
|
|
12
|
+
*
|
|
13
|
+
* This will get removed in v5
|
|
14
|
+
*/
|
|
5
15
|
maximumActiveExperiments?: number;
|
|
6
16
|
}>;
|
|
7
17
|
export declare const ExperimentsProvider: <Variant extends Reference>({ experiments, maximumActiveExperiments, children, }: React.PropsWithChildren<ExperimentsProviderProps<Variant>>) => JSX.Element;
|
|
@@ -2,12 +2,18 @@ import { Profile, ExperienceConfiguration, Reference, VariantRef } from '@nineta
|
|
|
2
2
|
export type JoinExperimentArgs = {
|
|
3
3
|
experiences: ExperienceConfiguration[];
|
|
4
4
|
experiment: ExperienceConfiguration<Reference | VariantRef>;
|
|
5
|
+
variant: VariantRef;
|
|
5
6
|
profile: Profile;
|
|
6
7
|
};
|
|
7
8
|
export type JoinExperiment = (args: JoinExperimentArgs) => Promise<void>;
|
|
8
9
|
type UseJoinExperimentArgs = {
|
|
9
10
|
experiments: ExperienceConfiguration[];
|
|
11
|
+
/**
|
|
12
|
+
* @deprecated
|
|
13
|
+
*
|
|
14
|
+
* This will get removed in v5 of the sdk
|
|
15
|
+
*/
|
|
10
16
|
maximumActiveExperiments?: number;
|
|
11
17
|
};
|
|
12
|
-
export declare const useProvideJoinExperiment: (
|
|
18
|
+
export declare const useProvideJoinExperiment: (_: UseJoinExperimentArgs) => (data: JoinExperimentArgs) => Promise<void>;
|
|
13
19
|
export {};
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { NinetailedPlugin, ExperienceConfiguration } from '@ninetailed/experience.js';
|
|
2
|
+
import { Ninetailed, NinetailedPlugin, ExperienceConfiguration } from '@ninetailed/experience.js';
|
|
3
3
|
import { Profile, Locale, OnErrorHandler, OnLogHandler } from '@ninetailed/experience.js-shared';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
type ExperimentProviderProps = {
|
|
5
|
+
/**
|
|
6
|
+
* @deprecated
|
|
7
|
+
*/
|
|
7
8
|
experiments?: ExperienceConfiguration<any>[];
|
|
9
|
+
/**
|
|
10
|
+
* @deprecated
|
|
11
|
+
*/
|
|
8
12
|
maximumActiveExperiments?: number;
|
|
13
|
+
};
|
|
14
|
+
export type NinetailedProviderInstantiationProps = {
|
|
15
|
+
clientId: string;
|
|
16
|
+
environment?: string;
|
|
9
17
|
preview?: boolean;
|
|
10
18
|
url?: string;
|
|
11
19
|
plugins?: (NinetailedPlugin | NinetailedPlugin[])[];
|
|
@@ -14,5 +22,9 @@ export type NinetailedProviderProps = {
|
|
|
14
22
|
requestTimeout?: number;
|
|
15
23
|
onLog?: OnLogHandler;
|
|
16
24
|
onError?: OnErrorHandler;
|
|
17
|
-
};
|
|
18
|
-
export
|
|
25
|
+
} & ExperimentProviderProps;
|
|
26
|
+
export type NinetailedProviderProps = NinetailedProviderInstantiationProps | ({
|
|
27
|
+
ninetailed: Ninetailed;
|
|
28
|
+
} & ExperimentProviderProps);
|
|
29
|
+
export declare const NinetailedProvider: (props: React.PropsWithChildren<NinetailedProviderProps>) => JSX.Element;
|
|
30
|
+
export {};
|
package/lib/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type { Profile, Variant } from '@ninetailed/experience.js-shared';
|
|
2
2
|
export type { ExperienceConfiguration, ExperienceType, EXPERIENCE_TRAIT_PREFIX, } from '@ninetailed/experience.js';
|
|
3
3
|
export { NinetailedProvider } from './NinetailedProvider';
|
|
4
|
-
export type { NinetailedProviderProps } from './NinetailedProvider';
|
|
4
|
+
export type { NinetailedProviderProps, NinetailedProviderInstantiationProps, } from './NinetailedProvider';
|
|
5
5
|
export { useNinetailed } from './useNinetailed';
|
|
6
6
|
export { useProfile } from './useProfile';
|
|
7
7
|
export { usePersonalize } from './usePersonalize';
|
package/lib/useProfile.d.ts
CHANGED
|
@@ -10,7 +10,6 @@ export declare const useProfile: () => {
|
|
|
10
10
|
status: "success";
|
|
11
11
|
profile: {
|
|
12
12
|
id: string;
|
|
13
|
-
stableId: string;
|
|
14
13
|
random: number;
|
|
15
14
|
audiences: string[];
|
|
16
15
|
traits: import("@ninetailed/experience.js-shared").Properties;
|
|
@@ -29,7 +28,6 @@ export declare const useProfile: () => {
|
|
|
29
28
|
timezone?: string | undefined;
|
|
30
29
|
};
|
|
31
30
|
session: {
|
|
32
|
-
id: string;
|
|
33
31
|
isReturningVisitor: boolean;
|
|
34
32
|
landingPage: {
|
|
35
33
|
path: string;
|
package/package.json
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ninetailed/experience.js-react",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0-beta.1",
|
|
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": "4.
|
|
11
|
-
"react-is": "18.2.0",
|
|
10
|
+
"@ninetailed/experience.js": "4.4.0-beta.1",
|
|
12
11
|
"react-intersection-observer": "8.34.0",
|
|
13
|
-
"@ninetailed/experience.js-shared": "4.
|
|
12
|
+
"@ninetailed/experience.js-shared": "4.4.0-beta.1",
|
|
14
13
|
"radash": "10.9.0",
|
|
15
14
|
"analytics": "0.8.1"
|
|
16
15
|
},
|