@ninetailed/experience.js-react 7.13.0 → 7.14.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
@@ -100,6 +100,7 @@ function __rest(s, e) {
100
100
  }
101
101
 
102
102
  function formatProfileForHook(profile) {
103
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
103
104
  const profileStateWithoutExperiences = __rest(profile, ["experiences"]);
104
105
  return Object.assign(Object.assign({}, profileStateWithoutExperiences), {
105
106
  loading: profile.status === 'loading'
@@ -152,13 +153,9 @@ const usePersonalize = (baseline, variants, options = {
152
153
  };
153
154
 
154
155
  /**
155
- * Custom hook to retrieve a specific feature flag from Ninetailed changes.
156
- *
157
- * @param flagKey - The key of the feature flag to retrieve
158
- * @param defaultValue - The default value to use if the flag is not found
159
- * @returns An object containing the flag value and status information
156
+ * Hook to access a Ninetailed variable flag with built-in tracking.
160
157
  */
161
- function useFlag(flagKey, defaultValue) {
158
+ function useFlag(flagKey, defaultValue, options = {}) {
162
159
  const ninetailed = useNinetailed();
163
160
  const lastProcessedState = React.useRef(null);
164
161
  const defaultValueRef = React.useRef(defaultValue);
@@ -168,7 +165,7 @@ function useFlag(flagKey, defaultValue) {
168
165
  status: 'loading',
169
166
  error: null
170
167
  });
171
- // Effect 1: Track changes to `flagKey` or `defaultValue`
168
+ // Reset on input change
172
169
  React.useEffect(() => {
173
170
  if (!radash.isEqual(defaultValueRef.current, defaultValue) || flagKeyRef.current !== flagKey) {
174
171
  defaultValueRef.current = defaultValue;
@@ -181,7 +178,7 @@ function useFlag(flagKey, defaultValue) {
181
178
  lastProcessedState.current = null;
182
179
  }
183
180
  }, [flagKey, defaultValue]);
184
- // Effect 2: Handle Ninetailed changes
181
+ // Track changes
185
182
  React.useEffect(() => {
186
183
  const unsubscribe = ninetailed.onChangesChange(changesState => {
187
184
  if (lastProcessedState.current && radash.isEqual(lastProcessedState.current, changesState)) {
@@ -207,11 +204,26 @@ function useFlag(flagKey, defaultValue) {
207
204
  try {
208
205
  const change = changesState.changes.find(change => change.key === flagKeyRef.current);
209
206
  if (change && change.type === experience_jsShared.ChangeTypes.Variable) {
207
+ const rawValue = change.value;
208
+ const actualValue = rawValue && typeof rawValue === 'object' && rawValue !== null && 'value' in rawValue && typeof rawValue['value'] === 'object' ? rawValue['value'] : rawValue;
210
209
  setResult({
211
- value: change.value,
210
+ value: actualValue,
212
211
  status: 'success',
213
212
  error: null
214
213
  });
214
+ const key = flagKeyRef.current;
215
+ const shouldTrack = typeof options.shouldTrack === 'function' ? options.shouldTrack() : options.shouldTrack !== false;
216
+ if (shouldTrack) {
217
+ ninetailed.trackVariableComponentView({
218
+ variable: change.value,
219
+ variant: {
220
+ id: `Variable-${key}`
221
+ },
222
+ componentType: 'Variable',
223
+ variantIndex: change.meta.variantIndex,
224
+ experienceId: change.meta.experienceId
225
+ });
226
+ }
215
227
  } else {
216
228
  setResult({
217
229
  value: defaultValueRef.current,
@@ -534,7 +546,9 @@ const Experience = _a => {
534
546
  const componentElement = componentRef.current;
535
547
  if (componentElement && !(componentElement instanceof Element)) {
536
548
  const isObject = typeof componentElement === 'object' && componentElement !== null;
537
- const constructorName = isObject ? componentElement.constructor.name : '';
549
+ const constructorName = isObject ?
550
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
551
+ componentElement.constructor.name : '';
538
552
  const isConstructorNameNotObject = constructorName && constructorName !== 'Object';
539
553
  logger.warn(`The component ref being in Experience is an invalid element. Expected an Element but got ${typeof componentElement}${isConstructorNameNotObject ? ` of type ${constructorName}` : ''}. This component won't be observed.`);
540
554
  return () => {
@@ -545,6 +559,7 @@ const Experience = _a => {
545
559
  observeElement({
546
560
  element: componentElement,
547
561
  experience,
562
+ componentType: 'Entry',
548
563
  audience,
549
564
  variant: isVariantHidden ? Object.assign(Object.assign({}, variant), {
550
565
  id: `${baseline.id}-hidden`
package/index.esm.js CHANGED
@@ -78,6 +78,7 @@ function _objectWithoutPropertiesLoose(source, excluded) {
78
78
 
79
79
  const _excluded$3 = ["experiences"];
80
80
  function formatProfileForHook(profile) {
81
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
81
82
  const profileStateWithoutExperiences = _objectWithoutPropertiesLoose(profile, _excluded$3);
82
83
  return Object.assign({}, profileStateWithoutExperiences, {
83
84
  loading: profile.status === 'loading'
@@ -133,13 +134,9 @@ const usePersonalize = (baseline, variants, options = {
133
134
  };
134
135
 
135
136
  /**
136
- * Custom hook to retrieve a specific feature flag from Ninetailed changes.
137
- *
138
- * @param flagKey - The key of the feature flag to retrieve
139
- * @param defaultValue - The default value to use if the flag is not found
140
- * @returns An object containing the flag value and status information
137
+ * Hook to access a Ninetailed variable flag with built-in tracking.
141
138
  */
142
- function useFlag(flagKey, defaultValue) {
139
+ function useFlag(flagKey, defaultValue, options = {}) {
143
140
  const ninetailed = useNinetailed();
144
141
  const lastProcessedState = useRef(null);
145
142
  const defaultValueRef = useRef(defaultValue);
@@ -150,7 +147,7 @@ function useFlag(flagKey, defaultValue) {
150
147
  error: null
151
148
  });
152
149
 
153
- // Effect 1: Track changes to `flagKey` or `defaultValue`
150
+ // Reset on input change
154
151
  useEffect(() => {
155
152
  if (!isEqual(defaultValueRef.current, defaultValue) || flagKeyRef.current !== flagKey) {
156
153
  defaultValueRef.current = defaultValue;
@@ -164,7 +161,7 @@ function useFlag(flagKey, defaultValue) {
164
161
  }
165
162
  }, [flagKey, defaultValue]);
166
163
 
167
- // Effect 2: Handle Ninetailed changes
164
+ // Track changes
168
165
  useEffect(() => {
169
166
  const unsubscribe = ninetailed.onChangesChange(changesState => {
170
167
  if (lastProcessedState.current && isEqual(lastProcessedState.current, changesState)) {
@@ -190,11 +187,26 @@ function useFlag(flagKey, defaultValue) {
190
187
  try {
191
188
  const change = changesState.changes.find(change => change.key === flagKeyRef.current);
192
189
  if (change && change.type === ChangeTypes.Variable) {
190
+ const rawValue = change.value;
191
+ const actualValue = rawValue && typeof rawValue === 'object' && rawValue !== null && 'value' in rawValue && typeof rawValue['value'] === 'object' ? rawValue['value'] : rawValue;
193
192
  setResult({
194
- value: change.value,
193
+ value: actualValue,
195
194
  status: 'success',
196
195
  error: null
197
196
  });
197
+ const key = flagKeyRef.current;
198
+ const shouldTrack = typeof options.shouldTrack === 'function' ? options.shouldTrack() : options.shouldTrack !== false;
199
+ if (shouldTrack) {
200
+ ninetailed.trackVariableComponentView({
201
+ variable: change.value,
202
+ variant: {
203
+ id: `Variable-${key}`
204
+ },
205
+ componentType: 'Variable',
206
+ variantIndex: change.meta.variantIndex,
207
+ experienceId: change.meta.experienceId
208
+ });
209
+ }
198
210
  } else {
199
211
  setResult({
200
212
  value: defaultValueRef.current,
@@ -520,7 +532,9 @@ const Experience = _ref2 => {
520
532
  const componentElement = componentRef.current;
521
533
  if (componentElement && !(componentElement instanceof Element)) {
522
534
  const isObject = typeof componentElement === 'object' && componentElement !== null;
523
- const constructorName = isObject ? componentElement.constructor.name : '';
535
+ const constructorName = isObject ?
536
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
537
+ componentElement.constructor.name : '';
524
538
  const isConstructorNameNotObject = constructorName && constructorName !== 'Object';
525
539
  logger.warn(`The component ref being in Experience is an invalid element. Expected an Element but got ${typeof componentElement}${isConstructorNameNotObject ? ` of type ${constructorName}` : ''}. This component won't be observed.`);
526
540
  return () => {
@@ -531,6 +545,7 @@ const Experience = _ref2 => {
531
545
  observeElement({
532
546
  element: componentElement,
533
547
  experience,
548
+ componentType: 'Entry',
534
549
  audience,
535
550
  variant: isVariantHidden ? Object.assign({}, variant, {
536
551
  id: `${baseline.id}-hidden`
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@ninetailed/experience.js-react",
3
- "version": "7.13.0",
3
+ "version": "7.14.0",
4
4
  "description": "Ninetailed SDK for React",
5
5
  "dependencies": {
6
- "@ninetailed/experience.js": "7.13.0",
7
- "@ninetailed/experience.js-shared": "7.13.0",
8
- "@ninetailed/experience.js-plugin-analytics": "7.13.0",
6
+ "@ninetailed/experience.js": "7.14.0",
7
+ "@ninetailed/experience.js-shared": "7.14.0",
8
+ "@ninetailed/experience.js-plugin-analytics": "7.14.0",
9
9
  "radash": "10.9.0",
10
10
  "react-is": "18.2.0"
11
11
  },
@@ -12,11 +12,11 @@ export type FlagResult<T> = {
12
12
  value: T;
13
13
  error: Error;
14
14
  };
15
+ type UseFlagOptions = {
16
+ shouldTrack?: boolean | (() => boolean);
17
+ };
15
18
  /**
16
- * Custom hook to retrieve a specific feature flag from Ninetailed changes.
17
- *
18
- * @param flagKey - The key of the feature flag to retrieve
19
- * @param defaultValue - The default value to use if the flag is not found
20
- * @returns An object containing the flag value and status information
19
+ * Hook to access a Ninetailed variable flag with built-in tracking.
21
20
  */
22
- export declare function useFlag<T extends AllowedVariableType>(flagKey: string, defaultValue: T): FlagResult<T>;
21
+ export declare function useFlag<T extends AllowedVariableType>(flagKey: string, defaultValue: T, options?: UseFlagOptions): FlagResult<T>;
22
+ export {};