@ninetailed/experience.js-react 4.4.0-beta.1 → 4.5.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 CHANGED
@@ -1929,6 +1929,23 @@ const useProfile = () => {
1929
1929
  });
1930
1930
  };
1931
1931
 
1932
+ const ExperimentsContext = /*#__PURE__*/React.createContext(undefined);
1933
+
1934
+ const useExperimentsContext = () => {
1935
+ const context = React.useContext(ExperimentsContext);
1936
+ if (context === undefined) {
1937
+ throw new Error('The component using the the context must be a descendant of the ExperimentsProvider');
1938
+ }
1939
+ return context;
1940
+ };
1941
+
1942
+ const useExperiments = () => {
1943
+ const context = useExperimentsContext();
1944
+ return {
1945
+ experiments: context.experiments
1946
+ };
1947
+ };
1948
+
1932
1949
  const useExperienceSelectionMiddleware = ({
1933
1950
  experiences,
1934
1951
  baseline,
@@ -1963,6 +1980,9 @@ const useExperience = ({
1963
1980
  experiences
1964
1981
  }) => {
1965
1982
  const profileState = useProfile();
1983
+ const {
1984
+ experiments
1985
+ } = useExperiments();
1966
1986
  const hasVariants = experiences.map(experience => experience_js.selectHasExperienceVariants(experience, baseline)).reduce((acc, curr) => acc || curr, false);
1967
1987
  const {
1968
1988
  status,
@@ -2019,7 +2039,7 @@ const useExperience = ({
2019
2039
  // @ts-ignore
2020
2040
  return overrideResult(emptyReturn);
2021
2041
  }
2022
- const activeExperiments = experience_js.selectActiveExperiments(experiences, profile);
2042
+ const activeExperiments = experience_js.selectActiveExperiments(experiments, profile);
2023
2043
  const experience = experience_js.selectExperience({
2024
2044
  experiences,
2025
2045
  activeExperiments,
@@ -2062,16 +2082,6 @@ const useExperience = ({
2062
2082
  }));
2063
2083
  };
2064
2084
 
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
-
2075
2085
  const useJoinExperiment = () => {
2076
2086
  const context = useExperimentsContext();
2077
2087
  return context.joinExperiment;
@@ -2145,17 +2155,14 @@ const Experience = _a => {
2145
2155
  });
2146
2156
  const joinExperiment = useJoinExperiment();
2147
2157
  React.useEffect(() => {
2148
- if (status === 'success' && experience && experience.type === 'nt_experiment' && variant && profile) {
2158
+ if (status === 'success' && experience && profile) {
2149
2159
  joinExperiment({
2150
2160
  experiences,
2151
2161
  experiment: experience,
2152
- variant: Object.assign(Object.assign({}, variant), {
2153
- hidden: 'hidden' in variant ? variant.hidden : false
2154
- }),
2155
2162
  profile
2156
2163
  });
2157
2164
  }
2158
- }, [status, experience, variant, profile]);
2165
+ }, [status, experience, profile]);
2159
2166
  if (!hasVariants) {
2160
2167
  return /*#__PURE__*/React.createElement(Component, Object.assign({}, passthroughProps, baseline, {
2161
2168
  key: baseline.id
@@ -2315,13 +2322,15 @@ const debounce = (fn, wait) => {
2315
2322
  debouncedFn();
2316
2323
  };
2317
2324
  };
2318
- // TODO: the majority of this code should be moved to the experience.js javascript package
2319
- const useProvideJoinExperiment = _ => {
2325
+ const useProvideJoinExperiment = ({
2326
+ experiments,
2327
+ maximumActiveExperiments: _maximumActiveExperiments = 1
2328
+ }) => {
2320
2329
  const {
2321
2330
  identify
2322
2331
  } = useNinetailed();
2323
2332
  const joinExperimentIdentify = debounce(args => {
2324
- const traits = args.reduce((traits, [experimentJoinTraits]) => {
2333
+ const traits = args.slice(0, _maximumActiveExperiments).reduce((traits, [experimentJoinTraits]) => {
2325
2334
  return Object.assign(Object.assign({}, experimentJoinTraits), traits);
2326
2335
  }, {});
2327
2336
  identify('', traits);
@@ -2329,7 +2338,6 @@ const useProvideJoinExperiment = _ => {
2329
2338
  return React.useCallback(data => __awaiter(void 0, void 0, void 0, function* () {
2330
2339
  const {
2331
2340
  experiment,
2332
- variant,
2333
2341
  profile
2334
2342
  } = data;
2335
2343
  const isExperiment = experiment.type === 'nt_experiment';
@@ -2337,17 +2345,17 @@ const useProvideJoinExperiment = _ => {
2337
2345
  experience_jsShared.logger.warn(`The experience ${experiment.id}, which you tried to join, is not an experiment.`);
2338
2346
  return;
2339
2347
  }
2340
- if (!experience_jsShared.isExperienceSticky(experiment)) {
2341
- experience_jsShared.logger.debug("Won't add experiment to traits, as it's not sticky.");
2348
+ const activeExperiments = experience_js.selectActiveExperiments(experiments, profile);
2349
+ if (activeExperiments.length >= _maximumActiveExperiments) {
2350
+ experience_jsShared.logger.warn(`The maximum number of active experiments (${_maximumActiveExperiments}) has been reached.`);
2342
2351
  return;
2343
2352
  }
2344
- const activeExperimentIds = experience_jsShared.selectActiveExperimentIds(profile);
2345
- if (activeExperimentIds.some(activeExperimentId => activeExperimentId === experiment.id)) {
2353
+ if (activeExperiments.some(activeExperiment => activeExperiment.id === experiment.id)) {
2346
2354
  experience_jsShared.logger.debug(`The user is already part of experiment ${experiment.id}. Won't join again.`);
2347
2355
  return;
2348
2356
  }
2349
2357
  joinExperimentIdentify({
2350
- [`${EXPERIENCE_TRAIT_PREFIX}${experiment.id}`]: variant.hidden ? 'hidden' : variant.id
2358
+ [`${EXPERIENCE_TRAIT_PREFIX}${experiment.id}`]: true
2351
2359
  });
2352
2360
  experience_jsShared.logger.debug(`Sent event to join experiment ${experiment.id}.`);
2353
2361
  }), []);
@@ -2358,7 +2366,10 @@ const ExperimentsProvider = ({
2358
2366
  maximumActiveExperiments: _maximumActiveExperiments = 1,
2359
2367
  children
2360
2368
  }) => {
2361
- const joinExperiment = useProvideJoinExperiment();
2369
+ const joinExperiment = useProvideJoinExperiment({
2370
+ experiments,
2371
+ maximumActiveExperiments: _maximumActiveExperiments
2372
+ });
2362
2373
  return jsxRuntime.jsx(ExperimentsContext.Provider, Object.assign({
2363
2374
  value: {
2364
2375
  experiments,
@@ -2369,18 +2380,6 @@ const ExperimentsProvider = ({
2369
2380
  }));
2370
2381
  };
2371
2382
 
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
2383
  const NinetailedProvider = props => {
2385
2384
  const ninetailed = React.useMemo(() => {
2386
2385
  if ('ninetailed' in props) {
@@ -2396,7 +2395,8 @@ const NinetailedProvider = props => {
2396
2395
  requestTimeout,
2397
2396
  plugins = [],
2398
2397
  onLog,
2399
- onError
2398
+ onError,
2399
+ buildClientContext
2400
2400
  } = props;
2401
2401
  return new experience_js.Ninetailed({
2402
2402
  clientId,
@@ -2409,18 +2409,21 @@ const NinetailedProvider = props => {
2409
2409
  locale,
2410
2410
  requestTimeout,
2411
2411
  onLog,
2412
- onError
2412
+ onError,
2413
+ buildClientContext
2413
2414
  });
2414
2415
  }, []);
2415
2416
  const {
2417
+ experiments = [],
2418
+ maximumActiveExperiments,
2416
2419
  children
2417
2420
  } = props;
2418
2421
  return jsxRuntime.jsx(NinetailedContext.Provider, Object.assign({
2419
2422
  value: ninetailed
2420
2423
  }, {
2421
2424
  children: jsxRuntime.jsx(ExperimentsProvider, Object.assign({
2422
- experiments: [],
2423
- maximumActiveExperiments: 10000
2425
+ experiments: experiments,
2426
+ maximumActiveExperiments: maximumActiveExperiments
2424
2427
  }, {
2425
2428
  children: children
2426
2429
  }))
package/index.js CHANGED
@@ -2,7 +2,7 @@ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
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
4
  import { useInView } from 'react-intersection-observer';
5
- import { isBrowser, logger, isExperienceSticky, selectActiveExperimentIds } from '@ninetailed/experience.js-shared';
5
+ import { isBrowser, logger } from '@ninetailed/experience.js-shared';
6
6
  import { isEqual, debounce as debounce$1, get as get$1 } from 'radash';
7
7
 
8
8
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -1921,6 +1921,23 @@ const useProfile = () => {
1921
1921
  });
1922
1922
  };
1923
1923
 
1924
+ const ExperimentsContext = /*#__PURE__*/createContext(undefined);
1925
+
1926
+ const useExperimentsContext = () => {
1927
+ const context = useContext(ExperimentsContext);
1928
+ if (context === undefined) {
1929
+ throw new Error('The component using the the context must be a descendant of the ExperimentsProvider');
1930
+ }
1931
+ return context;
1932
+ };
1933
+
1934
+ const useExperiments = () => {
1935
+ const context = useExperimentsContext();
1936
+ return {
1937
+ experiments: context.experiments
1938
+ };
1939
+ };
1940
+
1924
1941
  const useExperienceSelectionMiddleware = ({
1925
1942
  experiences,
1926
1943
  baseline,
@@ -1955,6 +1972,9 @@ const useExperience = ({
1955
1972
  experiences
1956
1973
  }) => {
1957
1974
  const profileState = useProfile();
1975
+ const {
1976
+ experiments
1977
+ } = useExperiments();
1958
1978
  const hasVariants = experiences.map(experience => selectHasExperienceVariants(experience, baseline)).reduce((acc, curr) => acc || curr, false);
1959
1979
  const {
1960
1980
  status,
@@ -2011,7 +2031,7 @@ const useExperience = ({
2011
2031
  // @ts-ignore
2012
2032
  return overrideResult(emptyReturn);
2013
2033
  }
2014
- const activeExperiments = selectActiveExperiments(experiences, profile);
2034
+ const activeExperiments = selectActiveExperiments(experiments, profile);
2015
2035
  const experience = selectExperience({
2016
2036
  experiences,
2017
2037
  activeExperiments,
@@ -2054,16 +2074,6 @@ const useExperience = ({
2054
2074
  }));
2055
2075
  };
2056
2076
 
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
-
2067
2077
  const useJoinExperiment = () => {
2068
2078
  const context = useExperimentsContext();
2069
2079
  return context.joinExperiment;
@@ -2137,17 +2147,14 @@ const Experience = _a => {
2137
2147
  });
2138
2148
  const joinExperiment = useJoinExperiment();
2139
2149
  useEffect(() => {
2140
- if (status === 'success' && experience && experience.type === 'nt_experiment' && variant && profile) {
2150
+ if (status === 'success' && experience && profile) {
2141
2151
  joinExperiment({
2142
2152
  experiences,
2143
2153
  experiment: experience,
2144
- variant: Object.assign(Object.assign({}, variant), {
2145
- hidden: 'hidden' in variant ? variant.hidden : false
2146
- }),
2147
2154
  profile
2148
2155
  });
2149
2156
  }
2150
- }, [status, experience, variant, profile]);
2157
+ }, [status, experience, profile]);
2151
2158
  if (!hasVariants) {
2152
2159
  return /*#__PURE__*/createElement$1(Component, Object.assign({}, passthroughProps, baseline, {
2153
2160
  key: baseline.id
@@ -2307,13 +2314,15 @@ const debounce = (fn, wait) => {
2307
2314
  debouncedFn();
2308
2315
  };
2309
2316
  };
2310
- // TODO: the majority of this code should be moved to the experience.js javascript package
2311
- const useProvideJoinExperiment = _ => {
2317
+ const useProvideJoinExperiment = ({
2318
+ experiments,
2319
+ maximumActiveExperiments: _maximumActiveExperiments = 1
2320
+ }) => {
2312
2321
  const {
2313
2322
  identify
2314
2323
  } = useNinetailed();
2315
2324
  const joinExperimentIdentify = debounce(args => {
2316
- const traits = args.reduce((traits, [experimentJoinTraits]) => {
2325
+ const traits = args.slice(0, _maximumActiveExperiments).reduce((traits, [experimentJoinTraits]) => {
2317
2326
  return Object.assign(Object.assign({}, experimentJoinTraits), traits);
2318
2327
  }, {});
2319
2328
  identify('', traits);
@@ -2321,7 +2330,6 @@ const useProvideJoinExperiment = _ => {
2321
2330
  return useCallback(data => __awaiter(void 0, void 0, void 0, function* () {
2322
2331
  const {
2323
2332
  experiment,
2324
- variant,
2325
2333
  profile
2326
2334
  } = data;
2327
2335
  const isExperiment = experiment.type === 'nt_experiment';
@@ -2329,17 +2337,17 @@ const useProvideJoinExperiment = _ => {
2329
2337
  logger.warn(`The experience ${experiment.id}, which you tried to join, is not an experiment.`);
2330
2338
  return;
2331
2339
  }
2332
- if (!isExperienceSticky(experiment)) {
2333
- logger.debug("Won't add experiment to traits, as it's not sticky.");
2340
+ const activeExperiments = selectActiveExperiments(experiments, profile);
2341
+ if (activeExperiments.length >= _maximumActiveExperiments) {
2342
+ logger.warn(`The maximum number of active experiments (${_maximumActiveExperiments}) has been reached.`);
2334
2343
  return;
2335
2344
  }
2336
- const activeExperimentIds = selectActiveExperimentIds(profile);
2337
- if (activeExperimentIds.some(activeExperimentId => activeExperimentId === experiment.id)) {
2345
+ if (activeExperiments.some(activeExperiment => activeExperiment.id === experiment.id)) {
2338
2346
  logger.debug(`The user is already part of experiment ${experiment.id}. Won't join again.`);
2339
2347
  return;
2340
2348
  }
2341
2349
  joinExperimentIdentify({
2342
- [`${EXPERIENCE_TRAIT_PREFIX}${experiment.id}`]: variant.hidden ? 'hidden' : variant.id
2350
+ [`${EXPERIENCE_TRAIT_PREFIX}${experiment.id}`]: true
2343
2351
  });
2344
2352
  logger.debug(`Sent event to join experiment ${experiment.id}.`);
2345
2353
  }), []);
@@ -2350,7 +2358,10 @@ const ExperimentsProvider = ({
2350
2358
  maximumActiveExperiments: _maximumActiveExperiments = 1,
2351
2359
  children
2352
2360
  }) => {
2353
- const joinExperiment = useProvideJoinExperiment();
2361
+ const joinExperiment = useProvideJoinExperiment({
2362
+ experiments,
2363
+ maximumActiveExperiments: _maximumActiveExperiments
2364
+ });
2354
2365
  return jsx(ExperimentsContext.Provider, Object.assign({
2355
2366
  value: {
2356
2367
  experiments,
@@ -2361,18 +2372,6 @@ const ExperimentsProvider = ({
2361
2372
  }));
2362
2373
  };
2363
2374
 
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
2375
  const NinetailedProvider = props => {
2377
2376
  const ninetailed = useMemo(() => {
2378
2377
  if ('ninetailed' in props) {
@@ -2388,7 +2387,8 @@ const NinetailedProvider = props => {
2388
2387
  requestTimeout,
2389
2388
  plugins = [],
2390
2389
  onLog,
2391
- onError
2390
+ onError,
2391
+ buildClientContext
2392
2392
  } = props;
2393
2393
  return new Ninetailed({
2394
2394
  clientId,
@@ -2401,18 +2401,21 @@ const NinetailedProvider = props => {
2401
2401
  locale,
2402
2402
  requestTimeout,
2403
2403
  onLog,
2404
- onError
2404
+ onError,
2405
+ buildClientContext
2405
2406
  });
2406
2407
  }, []);
2407
2408
  const {
2409
+ experiments = [],
2410
+ maximumActiveExperiments,
2408
2411
  children
2409
2412
  } = props;
2410
2413
  return jsx(NinetailedContext.Provider, Object.assign({
2411
2414
  value: ninetailed
2412
2415
  }, {
2413
2416
  children: jsx(ExperimentsProvider, Object.assign({
2414
- experiments: [],
2415
- maximumActiveExperiments: 10000
2417
+ experiments: experiments,
2418
+ maximumActiveExperiments: maximumActiveExperiments
2416
2419
  }, {
2417
2420
  children: children
2418
2421
  }))
@@ -1,17 +1,7 @@
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
- */
9
4
  experiments: ExperienceConfiguration<Variant>[];
10
- /**
11
- * @deprecated
12
- *
13
- * This will get removed in v5
14
- */
15
5
  maximumActiveExperiments?: number;
16
6
  }>;
17
7
  export declare const ExperimentsProvider: <Variant extends Reference>({ experiments, maximumActiveExperiments, children, }: React.PropsWithChildren<ExperimentsProviderProps<Variant>>) => JSX.Element;
@@ -1,8 +1,3 @@
1
- /**
2
- * @deprecated
3
- *
4
- * This will get removed in v5 of the SDK.
5
- */
6
1
  export declare const useExperiments: () => {
7
2
  experiments: import("@ninetailed/experience.js-shared").ExperienceConfiguration<any>[];
8
3
  };
@@ -2,18 +2,12 @@ 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;
6
5
  profile: Profile;
7
6
  };
8
7
  export type JoinExperiment = (args: JoinExperimentArgs) => Promise<void>;
9
8
  type UseJoinExperimentArgs = {
10
9
  experiments: ExperienceConfiguration[];
11
- /**
12
- * @deprecated
13
- *
14
- * This will get removed in v5 of the sdk
15
- */
16
10
  maximumActiveExperiments?: number;
17
11
  };
18
- export declare const useProvideJoinExperiment: (_: UseJoinExperimentArgs) => (data: JoinExperimentArgs) => Promise<void>;
12
+ export declare const useProvideJoinExperiment: ({ experiments, maximumActiveExperiments, }: UseJoinExperimentArgs) => (data: JoinExperimentArgs) => Promise<void>;
19
13
  export {};
@@ -1,14 +1,8 @@
1
1
  import React from 'react';
2
2
  import { Ninetailed, NinetailedPlugin, ExperienceConfiguration } from '@ninetailed/experience.js';
3
- import { Profile, Locale, OnErrorHandler, OnLogHandler } from '@ninetailed/experience.js-shared';
3
+ import { Profile, Locale, OnErrorHandler, OnLogHandler, NinetailedRequestContext } from '@ninetailed/experience.js-shared';
4
4
  type ExperimentProviderProps = {
5
- /**
6
- * @deprecated
7
- */
8
5
  experiments?: ExperienceConfiguration<any>[];
9
- /**
10
- * @deprecated
11
- */
12
6
  maximumActiveExperiments?: number;
13
7
  };
14
8
  export type NinetailedProviderInstantiationProps = {
@@ -22,6 +16,7 @@ export type NinetailedProviderInstantiationProps = {
22
16
  requestTimeout?: number;
23
17
  onLog?: OnLogHandler;
24
18
  onError?: OnErrorHandler;
19
+ buildClientContext?: () => NinetailedRequestContext;
25
20
  } & ExperimentProviderProps;
26
21
  export type NinetailedProviderProps = NinetailedProviderInstantiationProps | ({
27
22
  ninetailed: Ninetailed;
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@ninetailed/experience.js-react",
3
- "version": "4.4.0-beta.1",
3
+ "version": "4.5.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.4.0-beta.1",
10
+ "@ninetailed/experience.js": "4.5.0-beta.1",
11
11
  "react-intersection-observer": "8.34.0",
12
- "@ninetailed/experience.js-shared": "4.4.0-beta.1",
12
+ "@ninetailed/experience.js-shared": "4.5.0-beta.1",
13
13
  "radash": "10.9.0",
14
14
  "analytics": "0.8.1"
15
15
  },