@ninetailed/experience.js-react 7.22.0-alpha.3 → 7.23.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.js CHANGED
@@ -4,7 +4,6 @@ var jsxRuntime = require('react/jsx-runtime');
4
4
  var React = require('react');
5
5
  var experience_js = require('@ninetailed/experience.js');
6
6
  var experience_jsShared = require('@ninetailed/experience.js-shared');
7
- var radash = require('radash');
8
7
  var reactIs = require('react-is');
9
8
 
10
9
  const NinetailedContext = /*#__PURE__*/React.createContext(undefined);
@@ -126,7 +125,7 @@ const useProfile = () => {
126
125
  const unsubscribe = ninetailed.onProfileChange(changedProfileState => {
127
126
  // Skip update if the profile hasn't actually changed
128
127
  // Here we compare the entire profile including experiences and changes
129
- if (radash.isEqual(changedProfileState, profileStateRef.current)) {
128
+ if (experience_jsShared.isPlainDeepEqual(changedProfileState, profileStateRef.current)) {
130
129
  experience_jsShared.logger.debug('Profile State Did Not Change', changedProfileState);
131
130
  return;
132
131
  }
@@ -168,7 +167,7 @@ function useFlagWithManualTracking(flagKey, defaultValue) {
168
167
  });
169
168
  // Reset if inputs change
170
169
  React.useEffect(() => {
171
- if (!radash.isEqual(defaultValueRef.current, defaultValue) || flagKeyRef.current !== flagKey) {
170
+ if (!experience_jsShared.isPlainDeepEqual(defaultValueRef.current, defaultValue) || flagKeyRef.current !== flagKey) {
172
171
  defaultValueRef.current = defaultValue;
173
172
  flagKeyRef.current = flagKey;
174
173
  lastProcessedState.current = null;
@@ -183,7 +182,7 @@ function useFlagWithManualTracking(flagKey, defaultValue) {
183
182
  // Listen for personalization state changes
184
183
  React.useEffect(() => {
185
184
  const unsubscribe = ninetailed.onChangesChange(changesState => {
186
- if (lastProcessedState.current && radash.isEqual(lastProcessedState.current, changesState)) {
185
+ if (lastProcessedState.current && experience_jsShared.isPlainDeepEqual(lastProcessedState.current, changesState)) {
187
186
  return;
188
187
  }
189
188
  lastProcessedState.current = changesState;
@@ -365,11 +364,14 @@ const generateSelectors = id => {
365
364
  };
366
365
  const selectValueFromProfile = (profile, id) => {
367
366
  const selectors = generateSelectors(id);
368
- const matchingSelector = selectors.find(selector => radash.get(profile, selector));
367
+ // Selectors are matched by truthiness.
368
+ // Existing falsy values (e.g. 0, false, '') are treated as unresolved.
369
+ // It is currently unclear whether this is desired behavior or an accidental one.
370
+ const matchingSelector = selectors.find(selector => experience_jsShared.getByPath(profile, selector));
369
371
  if (!matchingSelector) {
370
372
  return null;
371
373
  }
372
- return radash.get(profile, matchingSelector);
374
+ return experience_jsShared.getByPath(profile, matchingSelector);
373
375
  };
374
376
 
375
377
  const MergeTag = ({
@@ -383,6 +385,8 @@ const MergeTag = ({
383
385
  if (loading || !profile) {
384
386
  return null;
385
387
  }
388
+ // Uses truthy fallback behavior: falsy resolved values (e.g. 0, false, '')
389
+ // are treated the same as unresolved values and will trigger the fallback if provided.
386
390
  const value = selectValueFromProfile(profile, id) || fallback;
387
391
  return value ? jsxRuntime.jsx(jsxRuntime.Fragment, {
388
392
  children: value
package/index.esm.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import React, { createContext, useMemo, useContext, useState, useRef, useEffect, useCallback, createElement, forwardRef } from 'react';
3
3
  import { Ninetailed, selectVariant, selectHasExperienceVariants } from '@ninetailed/experience.js';
4
- import { logger, ChangeTypes, isBrowser, circularJsonStringify } from '@ninetailed/experience.js-shared';
5
- import { isEqual, get } from 'radash';
4
+ import { isPlainDeepEqual, logger, ChangeTypes, isBrowser, getByPath, circularJsonStringify } from '@ninetailed/experience.js-shared';
6
5
  import { isForwardRef } from 'react-is';
7
6
 
8
7
  const NinetailedContext = /*#__PURE__*/createContext(undefined);
@@ -124,7 +123,7 @@ const useProfile = () => {
124
123
  const unsubscribe = ninetailed.onProfileChange(changedProfileState => {
125
124
  // Skip update if the profile hasn't actually changed
126
125
  // Here we compare the entire profile including experiences and changes
127
- if (isEqual(changedProfileState, profileStateRef.current)) {
126
+ if (isPlainDeepEqual(changedProfileState, profileStateRef.current)) {
128
127
  logger.debug('Profile State Did Not Change', changedProfileState);
129
128
  return;
130
129
  }
@@ -166,7 +165,7 @@ function useFlagWithManualTracking(flagKey, defaultValue) {
166
165
  });
167
166
  // Reset if inputs change
168
167
  useEffect(() => {
169
- if (!isEqual(defaultValueRef.current, defaultValue) || flagKeyRef.current !== flagKey) {
168
+ if (!isPlainDeepEqual(defaultValueRef.current, defaultValue) || flagKeyRef.current !== flagKey) {
170
169
  defaultValueRef.current = defaultValue;
171
170
  flagKeyRef.current = flagKey;
172
171
  lastProcessedState.current = null;
@@ -181,7 +180,7 @@ function useFlagWithManualTracking(flagKey, defaultValue) {
181
180
  // Listen for personalization state changes
182
181
  useEffect(() => {
183
182
  const unsubscribe = ninetailed.onChangesChange(changesState => {
184
- if (lastProcessedState.current && isEqual(lastProcessedState.current, changesState)) {
183
+ if (lastProcessedState.current && isPlainDeepEqual(lastProcessedState.current, changesState)) {
185
184
  return;
186
185
  }
187
186
  lastProcessedState.current = changesState;
@@ -363,11 +362,14 @@ const generateSelectors = id => {
363
362
  };
364
363
  const selectValueFromProfile = (profile, id) => {
365
364
  const selectors = generateSelectors(id);
366
- const matchingSelector = selectors.find(selector => get(profile, selector));
365
+ // Selectors are matched by truthiness.
366
+ // Existing falsy values (e.g. 0, false, '') are treated as unresolved.
367
+ // It is currently unclear whether this is desired behavior or an accidental one.
368
+ const matchingSelector = selectors.find(selector => getByPath(profile, selector));
367
369
  if (!matchingSelector) {
368
370
  return null;
369
371
  }
370
- return get(profile, matchingSelector);
372
+ return getByPath(profile, matchingSelector);
371
373
  };
372
374
 
373
375
  const MergeTag = ({
@@ -381,6 +383,8 @@ const MergeTag = ({
381
383
  if (loading || !profile) {
382
384
  return null;
383
385
  }
386
+ // Uses truthy fallback behavior: falsy resolved values (e.g. 0, false, '')
387
+ // are treated the same as unresolved values and will trigger the fallback if provided.
384
388
  const value = selectValueFromProfile(profile, id) || fallback;
385
389
  return value ? jsx(Fragment, {
386
390
  children: value
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ninetailed/experience.js-react",
3
- "version": "7.22.0-alpha.3",
3
+ "version": "7.23.0",
4
4
  "description": "Ninetailed SDK for React",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -28,10 +28,9 @@
28
28
  },
29
29
  "sideEffects": false,
30
30
  "dependencies": {
31
- "@ninetailed/experience.js": "7.22.0-alpha.3",
32
- "@ninetailed/experience.js-shared": "7.22.0-alpha.3",
33
- "@ninetailed/experience.js-plugin-analytics": "7.22.0-alpha.3",
34
- "radash": "10.9.0",
31
+ "@ninetailed/experience.js": "7.23.0",
32
+ "@ninetailed/experience.js-shared": "7.23.0",
33
+ "@ninetailed/experience.js-plugin-analytics": "7.23.0",
35
34
  "react-is": "19.2.4"
36
35
  },
37
36
  "peerDependencies": {
@@ -17,6 +17,9 @@ export type NinetailedProviderInstantiationProps = {
17
17
  buildClientContext?: () => NinetailedRequestContext;
18
18
  onInitProfileId?: OnInitProfileId;
19
19
  storageImpl?: Storage;
20
+ /**
21
+ * @deprecated This option is deprecated and will be removed in a future major version.
22
+ */
20
23
  useSDKEvaluation?: boolean;
21
24
  };
22
25
  export type NinetailedProviderProps = NinetailedProviderInstantiationProps | {