@wlloyalty/wll-react-sdk 1.0.102 → 1.0.104

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.
@@ -4,6 +4,7 @@ import { NavigationConfig } from '../types/navigation';
4
4
  import { TSection } from '../types/section';
5
5
  import { BaseThemeObject, ThemeContextType } from '../types/theme';
6
6
  import { CTALinkTarget, Tile } from '../types/tile';
7
+ import { EventTypes } from '../utils/eventEmitter';
7
8
  type Fetcher = <T>(endpoint: string, options?: RequestInit) => Promise<APIResponse<T>>;
8
9
  export type SDKConfig = {
9
10
  apiKey: string;
@@ -22,6 +23,8 @@ type WllSdkContextType = ThemeContextType & {
22
23
  getTileByID: (id: string) => Promise<APIResponse<Tile>>;
23
24
  handleNavigation: (link: string, target: CTALinkTarget) => Promise<void>;
24
25
  refreshGroup: (id: string) => Promise<APIResponse<TGroup>>;
26
+ notifyDataChange: (eventType: EventTypes, data?: any) => void;
27
+ subscribeToDataChange: (eventType: EventTypes, callback: (data?: any) => void) => () => void;
25
28
  } & Readonly<{
26
29
  readonly config: SDKConfig;
27
30
  }>;
@@ -23,6 +23,7 @@ export declare const createBadgeTileMock: (config?: BadgeTileMockConfig) => {
23
23
  defaultLocale: string;
24
24
  locale: string;
25
25
  createdAt: string;
26
+ lastEarnedAt: string;
26
27
  updatedAt: string;
27
28
  awardedDatePrefix: string;
28
29
  emptyBadgeMessage: string;
@@ -106,6 +106,7 @@ export declare class BadgeTileConfig {
106
106
  emptyBadgeArtworkUrl?: string;
107
107
  awardedDatePrefix?: string;
108
108
  badgeNotEarnedMessage?: string;
109
+ lastEarnedAt?: string;
109
110
  }
110
111
  export type BadgeDetail = {
111
112
  name: string;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Type definition for event callback functions
3
+ * @typedef {function} EventCallback
4
+ * @param {any} [data] - Optional data passed with the event
5
+ */
6
+ export type EventCallback = (data?: any) => void;
7
+ /**
8
+ * Supported event types for the SDK event system
9
+ * @typedef {string} EventTypes
10
+ */
11
+ export type EventTypes = 'GROUP_DATA_CHANGED' | 'SECTION_DATA_CHANGED' | 'TILE_DATA_CHANGED' | string;
12
+ /**
13
+ * A simple event emitter for handling SDK events
14
+ * Provides a pub-sub mechanism for components to communicate
15
+ */
16
+ export declare class EventEmitter {
17
+ /**
18
+ * Map of event types to arrays of callback functions
19
+ * @private
20
+ */
21
+ private events;
22
+ /**
23
+ * Subscribe to an event
24
+ * @param {EventTypes} event - The event type to subscribe to
25
+ * @param {EventCallback} callback - The callback function to execute when the event is emitted
26
+ * @returns {Function} An unsubscribe function that removes this callback when called
27
+ */
28
+ on(event: EventTypes, callback: EventCallback): () => void;
29
+ /**
30
+ * Emit an event with optional data
31
+ * @param {EventTypes} event - The event type to emit
32
+ * @param {any} [data] - Optional data to pass to the event callbacks
33
+ */
34
+ emit(event: EventTypes, data?: any): void;
35
+ /**
36
+ * Remove all event listeners
37
+ * Use this method to clean up when the event emitter is no longer needed
38
+ */
39
+ clear(): void;
40
+ }
41
+ /**
42
+ * Singleton instance of the EventEmitter for use throughout the SDK
43
+ */
44
+ export declare const sdkEventEmitter: EventEmitter;
@@ -5,3 +5,16 @@ import { Tile } from '../types/tile';
5
5
  * @returns Sorted array of tiles
6
6
  */
7
7
  export declare const sortByPriority: <T extends Pick<Tile, "priority">>(tiles: T[]) => T[];
8
+ /**
9
+ * Transforms locale to a locale that is supported by the browser
10
+ * @param locale Two-letter locale code to transform (en, fr, etc.)
11
+ * @returns Full locale string (e.g., en-GB, fr-FR)
12
+ */
13
+ export declare const transformLocale: (locale?: string | null) => string;
14
+ /**
15
+ * Formats a date string to a localized date string based on user locale
16
+ * @param date Date string to format
17
+ * @param userLocale User's locale (defaults to 'en')
18
+ * @returns Formatted date string or fallback message
19
+ */
20
+ export declare const handleLastEarnedDate: (date?: string, userLocale?: string) => string;
package/dist/web.js CHANGED
@@ -7924,6 +7924,68 @@ var useGetGroupByID = createResourceGetter('groups', true);
7924
7924
  var useGetSectionByID = createResourceGetter('sections');
7925
7925
  var useGetTileByID = createResourceGetter('tiles');
7926
7926
 
7927
+ /**
7928
+ * A simple event emitter for handling SDK events
7929
+ * Provides a pub-sub mechanism for components to communicate
7930
+ */
7931
+ var EventEmitter$1 = /** @class */function () {
7932
+ function EventEmitter() {
7933
+ /**
7934
+ * Map of event types to arrays of callback functions
7935
+ * @private
7936
+ */
7937
+ this.events = new Map();
7938
+ }
7939
+ /**
7940
+ * Subscribe to an event
7941
+ * @param {EventTypes} event - The event type to subscribe to
7942
+ * @param {EventCallback} callback - The callback function to execute when the event is emitted
7943
+ * @returns {Function} An unsubscribe function that removes this callback when called
7944
+ */
7945
+ EventEmitter.prototype.on = function (event, callback) {
7946
+ var _this = this;
7947
+ var _a;
7948
+ if (!this.events.has(event)) {
7949
+ this.events.set(event, []);
7950
+ }
7951
+ (_a = this.events.get(event)) === null || _a === void 0 ? void 0 : _a.push(callback);
7952
+ return function () {
7953
+ var callbacks = _this.events.get(event);
7954
+ if (callbacks) {
7955
+ var index = callbacks.indexOf(callback);
7956
+ if (index !== -1) {
7957
+ callbacks.splice(index, 1);
7958
+ }
7959
+ }
7960
+ };
7961
+ };
7962
+ /**
7963
+ * Emit an event with optional data
7964
+ * @param {EventTypes} event - The event type to emit
7965
+ * @param {any} [data] - Optional data to pass to the event callbacks
7966
+ */
7967
+ EventEmitter.prototype.emit = function (event, data) {
7968
+ var callbacks = this.events.get(event);
7969
+ if (callbacks) {
7970
+ callbacks.forEach(function (callback) {
7971
+ return callback(data);
7972
+ });
7973
+ }
7974
+ };
7975
+ /**
7976
+ * Remove all event listeners
7977
+ * Use this method to clean up when the event emitter is no longer needed
7978
+ */
7979
+ EventEmitter.prototype.clear = function () {
7980
+ this.events.clear();
7981
+ };
7982
+ return EventEmitter;
7983
+ }();
7984
+ /**
7985
+ * Singleton instance of the EventEmitter for use throughout the SDK
7986
+ */
7987
+ var sdkEventEmitter = new EventEmitter$1();
7988
+
7927
7989
  var sizes = {
7928
7990
  borderRadiusSm: 15,
7929
7991
  borderRadiusLg: 20,
@@ -8525,6 +8587,12 @@ var WllSdkProvider = function (_a) {
8525
8587
  });
8526
8588
  });
8527
8589
  }, [getGroupByID]);
8590
+ var notifyDataChange = React.useCallback(function (eventType, data) {
8591
+ sdkEventEmitter.emit(eventType, data);
8592
+ }, []);
8593
+ var subscribeToDataChange = React.useCallback(function (eventType, callback) {
8594
+ return sdkEventEmitter.on(eventType, callback);
8595
+ }, []);
8528
8596
  var contextValue = React.useMemo(function () {
8529
8597
  return {
8530
8598
  theme: theme,
@@ -8534,9 +8602,11 @@ var WllSdkProvider = function (_a) {
8534
8602
  getTileByID: getTileByID,
8535
8603
  handleNavigation: handleNavigation,
8536
8604
  refreshGroup: refreshGroup,
8605
+ notifyDataChange: notifyDataChange,
8606
+ subscribeToDataChange: subscribeToDataChange,
8537
8607
  config: config
8538
8608
  };
8539
- }, [theme, setTheme, getGroupByID, getSectionByID, getTileByID, handleNavigation, refreshGroup, config]);
8609
+ }, [theme, setTheme, getGroupByID, getSectionByID, getTileByID, handleNavigation, refreshGroup, notifyDataChange, subscribeToDataChange, config]);
8540
8610
  return /*#__PURE__*/React.createElement(WllSdkContext.Provider, {
8541
8611
  value: contextValue
8542
8612
  }, /*#__PURE__*/React.createElement(ResponsiveProvider, null, children));
@@ -19193,7 +19263,7 @@ var BaseTileBody = function (props) {
19193
19263
  return /*#__PURE__*/React.createElement(Text, __assign({
19194
19264
  variant: "body"
19195
19265
  }, props, {
19196
- accessibilityRole: "text",
19266
+ role: "article",
19197
19267
  accessibilityLabel: body,
19198
19268
  numberOfLines: getNumberOfLines(),
19199
19269
  testID: "tile-body"
@@ -19317,7 +19387,7 @@ var BaseTileContent = function (_a) {
19317
19387
  justifyContent: 'center',
19318
19388
  height: !artworkUrl ? '100%' : undefined
19319
19389
  }],
19320
- accessibilityRole: "none"
19390
+ role: "none"
19321
19391
  }, children);
19322
19392
  };
19323
19393
 
@@ -19345,7 +19415,7 @@ var BaseTileHeader = function (_a) {
19345
19415
  return /*#__PURE__*/React.createElement(View$2, {
19346
19416
  style: combinedStyle,
19347
19417
  testID: "tile-header",
19348
- accessibilityRole: "header"
19418
+ role: "heading"
19349
19419
  }, children);
19350
19420
  };
19351
19421
 
@@ -19371,7 +19441,7 @@ var BaseTileMedia = function (props) {
19371
19441
  testID: "tile-media",
19372
19442
  style: [props.style, baseStyles.media, styles.media],
19373
19443
  alt: "Content image".concat(title ? " for ".concat(title) : ''),
19374
- accessibilityRole: "image"
19444
+ role: "img"
19375
19445
  }));
19376
19446
  };
19377
19447
 
@@ -19397,7 +19467,7 @@ var BaseTileTitle = function () {
19397
19467
  if (isHalfSize && artworkUrl || !title) return null;
19398
19468
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, {
19399
19469
  variant: "title",
19400
- accessibilityRole: "header",
19470
+ role: "heading",
19401
19471
  accessibilityLabel: title,
19402
19472
  numberOfLines: 1,
19403
19473
  testID: "tile-title"
@@ -19465,7 +19535,7 @@ var BaseTileContainer = function (_a) {
19465
19535
  onPress: handlePress,
19466
19536
  disabled: tile.type !== 'REWARD' && tile.type !== 'REWARD_CATEGORY' && !ctaLink,
19467
19537
  accessible: true,
19468
- accessibilityRole: "button",
19538
+ role: "button",
19469
19539
  accessibilityLabel: "".concat(title).concat(ctaLink ? ' - Click to open' : ''),
19470
19540
  accessibilityState: {
19471
19541
  disabled: !ctaLink
@@ -19728,6 +19798,63 @@ function withTileFetching(WrappedComponent) {
19728
19798
  };
19729
19799
  }
19730
19800
 
19801
+ /**
19802
+ * Sorts tiles by priority (higher priority first) and maintains original order for equal priorities
19803
+ * @param tiles Array of tiles to sort
19804
+ * @returns Sorted array of tiles
19805
+ */
19806
+ var sortByPriority = function (tiles) {
19807
+ return __spreadArray([], tiles, true).sort(function (a, b) {
19808
+ // Sort by priority (higher priority first)
19809
+ if (a.priority !== b.priority) {
19810
+ return b.priority - a.priority;
19811
+ }
19812
+ // If priorities are equal, maintain original order
19813
+ return tiles.indexOf(a) - tiles.indexOf(b);
19814
+ });
19815
+ };
19816
+ /**
19817
+ * Transforms locale to a locale that is supported by the browser
19818
+ * @param locale Two-letter locale code to transform (en, fr, etc.)
19819
+ * @returns Full locale string (e.g., en-GB, fr-FR)
19820
+ */
19821
+ var transformLocale = function (locale) {
19822
+ var localeMapping = {
19823
+ en: 'en-GB',
19824
+ fr: 'fr-FR',
19825
+ es: 'es-ES',
19826
+ de: 'de-DE',
19827
+ it: 'it-IT',
19828
+ pt: 'pt-PT',
19829
+ us: 'en-US'
19830
+ };
19831
+ var languageCode = (locale !== null && locale !== void 0 ? locale : 'en').toLowerCase();
19832
+ return localeMapping[languageCode] || 'en-GB';
19833
+ };
19834
+ /**
19835
+ * Formats a date string to a localized date string based on user locale
19836
+ * @param date Date string to format
19837
+ * @param userLocale User's locale (defaults to 'en')
19838
+ * @returns Formatted date string or fallback message
19839
+ */
19840
+ var handleLastEarnedDate = function (date, userLocale) {
19841
+ if (userLocale === void 0) {
19842
+ userLocale = 'en';
19843
+ }
19844
+ if (!date) return 'Date not available';
19845
+ try {
19846
+ var formattedLocale = transformLocale(userLocale);
19847
+ var dateObj = new Date(date);
19848
+ if (isNaN(dateObj.getTime())) {
19849
+ return 'Invalid Date';
19850
+ }
19851
+ return dateObj.toLocaleDateString(formattedLocale);
19852
+ } catch (error) {
19853
+ console.error('Error formatting date:', error);
19854
+ return 'Invalid Date';
19855
+ }
19856
+ };
19857
+
19731
19858
  /**
19732
19859
  * Custom hook that returns the styles for the BadgeTile component.
19733
19860
  * Applies responsive styling based on the current device.
@@ -19795,9 +19922,10 @@ var BadgeTileDateEarned = function () {
19795
19922
  var _a = tileContext.configuration,
19796
19923
  count = _a.count,
19797
19924
  awardedDatePrefix = _a.awardedDatePrefix,
19798
- createdAt = _a.createdAt,
19925
+ lastEarnedAt = _a.lastEarnedAt,
19799
19926
  badgeNotEarnedMessage = _a.badgeNotEarnedMessage,
19800
- type = _a.type;
19927
+ type = _a.type,
19928
+ locale = _a.locale;
19801
19929
  // Don't show for Latest type with count=0
19802
19930
  if (type === exports.BadgeTileType.Latest && count === 0) {
19803
19931
  return null;
@@ -19811,8 +19939,8 @@ var BadgeTileDateEarned = function () {
19811
19939
  backgroundColor: backgroundColor
19812
19940
  }];
19813
19941
  var textColor = getReadableTextColor(backgroundColor);
19814
- var displayText = count === 0 ? badgeNotEarnedMessage : "".concat(awardedDatePrefix, " ").concat(new Date(createdAt).toLocaleDateString());
19815
- var accessibilityLabel = count === 0 ? 'Badge not yet earned' : "Badge earned on ".concat(new Date(createdAt).toLocaleDateString());
19942
+ var displayText = count === 0 ? badgeNotEarnedMessage : "".concat(awardedDatePrefix, " ").concat(handleLastEarnedDate(lastEarnedAt, locale));
19943
+ var accessibilityLabel = count === 0 ? 'Badge not yet earned' : "Badge earned on ".concat(handleLastEarnedDate(lastEarnedAt, locale));
19816
19944
  return /*#__PURE__*/React.createElement(View$2, {
19817
19945
  style: containerStyle,
19818
19946
  accessible: true,
@@ -20066,7 +20194,7 @@ var BannerTileDescription = function () {
20066
20194
  if (!description) return null;
20067
20195
  return /*#__PURE__*/React.createElement(Text, {
20068
20196
  style: styles.description,
20069
- accessibilityRole: "text",
20197
+ role: "article",
20070
20198
  accessibilityLabel: description,
20071
20199
  testID: "banner-tile-description"
20072
20200
  }, description);
@@ -20091,7 +20219,7 @@ var BannerTileMedia = function (_a) {
20091
20219
  };
20092
20220
  return /*#__PURE__*/React.createElement(View$2, {
20093
20221
  style: [styles.mediaContainer, containerStyle],
20094
- accessibilityRole: "image",
20222
+ role: "img",
20095
20223
  accessibilityLabel: "Banner image".concat(title ? " for ".concat(title) : ''),
20096
20224
  testID: "banner-tile-media"
20097
20225
  }, /*#__PURE__*/React.createElement(ProgressiveImage, {
@@ -20118,7 +20246,7 @@ var BannerTileTitle = function () {
20118
20246
  variant: "title",
20119
20247
  testID: "banner-tile-title",
20120
20248
  style: styles.title,
20121
- accessibilityRole: "header",
20249
+ role: "heading",
20122
20250
  accessibilityLabel: title
20123
20251
  }, title);
20124
20252
  };
@@ -20245,7 +20373,7 @@ var ContentTileMedia = function (_a) {
20245
20373
  return /*#__PURE__*/React.createElement(View$2, {
20246
20374
  style: [styles.imageContainer, containerStyle],
20247
20375
  testID: "content-tile-media",
20248
- accessibilityRole: "image",
20376
+ role: "img",
20249
20377
  accessibilityLabel: "Image for ".concat(title)
20250
20378
  }, /*#__PURE__*/React.createElement(ProgressiveImage, {
20251
20379
  source: {
@@ -20270,7 +20398,7 @@ var ContentTileSummary = function () {
20270
20398
  };
20271
20399
  return /*#__PURE__*/React.createElement(Text, {
20272
20400
  variant: "body",
20273
- accessibilityRole: "text",
20401
+ role: "article",
20274
20402
  accessibilityLabel: body,
20275
20403
  numberOfLines: getNumberOfLines(),
20276
20404
  testID: "content-tile-summary"
@@ -20292,7 +20420,7 @@ var ContentTileTitle = function () {
20292
20420
  };
20293
20421
  return /*#__PURE__*/React.createElement(Text, {
20294
20422
  variant: "title",
20295
- accessibilityRole: "header",
20423
+ role: "heading",
20296
20424
  accessibilityLabel: title,
20297
20425
  numberOfLines: 1,
20298
20426
  style: handleTitleWidth(),
@@ -20351,22 +20479,6 @@ var ContentTile = Object.assign(ContentTileRoot, {
20351
20479
  });
20352
20480
  var ContentTile$1 = withTileFetching(ContentTile);
20353
20481
 
20354
- /**
20355
- * Sorts tiles by priority (higher priority first) and maintains original order for equal priorities
20356
- * @param tiles Array of tiles to sort
20357
- * @returns Sorted array of tiles
20358
- */
20359
- var sortByPriority = function (tiles) {
20360
- return __spreadArray([], tiles, true).sort(function (a, b) {
20361
- // Sort by priority (higher priority first)
20362
- if (a.priority !== b.priority) {
20363
- return b.priority - a.priority;
20364
- }
20365
- // If priorities are equal, maintain original order
20366
- return tiles.indexOf(a) - tiles.indexOf(b);
20367
- });
20368
- };
20369
-
20370
20482
  exports.SectionType = void 0;
20371
20483
  (function (SectionType) {
20372
20484
  SectionType["Grid"] = "GRID";
@@ -21005,7 +21117,7 @@ var EmptyState = function (_a) {
21005
21117
  var message = _a.message;
21006
21118
  return /*#__PURE__*/React.createElement(View$2, {
21007
21119
  style: commonStyles.emptyContainer,
21008
- accessibilityRole: "text",
21120
+ role: "article",
21009
21121
  accessibilityLabel: "Empty state: ".concat(message)
21010
21122
  }, /*#__PURE__*/React.createElement(Text$3, null, message));
21011
21123
  };
@@ -21107,6 +21219,14 @@ var useGroupContext = function () {
21107
21219
  /**
21108
21220
  * Custom hook to fetch and manage group data
21109
21221
  *
21222
+ * This hook handles two distinct data fetching scenarios:
21223
+ * 1. Initial fetch: Shows loading state while first loading data
21224
+ * 2. Background refresh: Updates data silently without loading states
21225
+ *
21226
+ * The hook subscribes to GROUP_DATA_CHANGED events to refresh data
21227
+ * when notified by the host application, ensuring UI remains responsive
21228
+ * without showing loading indicators during refreshes.
21229
+ *
21110
21230
  * @param {string} id - The ID of the group to fetch
21111
21231
  * @returns {Object} Object containing group data, loading state, and any error
21112
21232
  */
@@ -21121,27 +21241,22 @@ var useGroupData = function (id) {
21121
21241
  var _c = React.useState(true),
21122
21242
  isLoading = _c[0],
21123
21243
  setIsLoading = _c[1];
21124
- var fetchGroup = React.useCallback(function () {
21125
- var args_1 = [];
21126
- for (var _i = 0; _i < arguments.length; _i++) {
21127
- args_1[_i] = arguments[_i];
21128
- }
21129
- return __awaiter(void 0, __spreadArray([], args_1, true), void 0, function (showLoading) {
21244
+ var _d = React.useState(false),
21245
+ isInitialFetchDone = _d[0],
21246
+ setIsInitialFetchDone = _d[1];
21247
+ var initialFetch = React.useCallback(function () {
21248
+ return __awaiter(void 0, void 0, void 0, function () {
21130
21249
  var response, err_1;
21131
- if (showLoading === void 0) {
21132
- showLoading = true;
21133
- }
21134
21250
  return __generator(this, function (_a) {
21135
21251
  switch (_a.label) {
21136
21252
  case 0:
21137
21253
  if (!id || !sdk || !sdk.getGroupByID) {
21138
21254
  setError('Unable to fetch group data: invalid configuration');
21139
21255
  setIsLoading(false);
21256
+ setIsInitialFetchDone(true);
21140
21257
  return [2 /*return*/];
21141
21258
  }
21142
- if (showLoading) {
21143
- setIsLoading(true);
21144
- }
21259
+ setIsLoading(true);
21145
21260
  setError(null);
21146
21261
  _a.label = 1;
21147
21262
  case 1:
@@ -21161,9 +21276,8 @@ var useGroupData = function (id) {
21161
21276
  console.error('Error fetching group:', err_1);
21162
21277
  return [3 /*break*/, 5];
21163
21278
  case 4:
21164
- if (showLoading) {
21165
- setIsLoading(false);
21166
- }
21279
+ setIsLoading(false);
21280
+ setIsInitialFetchDone(true);
21167
21281
  return [7 /*endfinally*/];
21168
21282
  case 5:
21169
21283
  return [2 /*return*/];
@@ -21171,12 +21285,49 @@ var useGroupData = function (id) {
21171
21285
  });
21172
21286
  });
21173
21287
  }, [id, sdk]);
21288
+ var silentRefresh = React.useCallback(function () {
21289
+ return __awaiter(void 0, void 0, void 0, function () {
21290
+ var response, err_2;
21291
+ return __generator(this, function (_a) {
21292
+ switch (_a.label) {
21293
+ case 0:
21294
+ if (!id || !sdk || !sdk.getGroupByID || !isInitialFetchDone) {
21295
+ return [2 /*return*/];
21296
+ }
21297
+ _a.label = 1;
21298
+ case 1:
21299
+ _a.trys.push([1, 3,, 4]);
21300
+ return [4 /*yield*/, sdk.refreshGroup(id)];
21301
+ case 2:
21302
+ response = _a.sent();
21303
+ if (response && response.status === 'success' && response.data) {
21304
+ setGroupData(response.data);
21305
+ }
21306
+ return [3 /*break*/, 4];
21307
+ case 3:
21308
+ err_2 = _a.sent();
21309
+ console.error('Error during silent refresh:', err_2);
21310
+ return [3 /*break*/, 4];
21311
+ case 4:
21312
+ return [2 /*return*/];
21313
+ }
21314
+ });
21315
+ });
21316
+ }, [id, sdk, isInitialFetchDone]);
21174
21317
  var refreshGroup = React.useCallback(function () {
21175
- return fetchGroup(false);
21176
- }, [fetchGroup]);
21318
+ return silentRefresh();
21319
+ }, [silentRefresh]);
21177
21320
  React.useEffect(function () {
21178
- fetchGroup(true);
21179
- }, [fetchGroup]);
21321
+ if (sdk) {
21322
+ initialFetch();
21323
+ var unsubscribeGroup_1 = sdk.subscribeToDataChange('GROUP_DATA_CHANGED', function () {
21324
+ silentRefresh();
21325
+ });
21326
+ return function () {
21327
+ unsubscribeGroup_1();
21328
+ };
21329
+ }
21330
+ }, [initialFetch, id, sdk, silentRefresh]);
21180
21331
  return {
21181
21332
  groupData: groupData,
21182
21333
  isLoading: isLoading,
@@ -21273,7 +21424,7 @@ var Group = function (_a) {
21273
21424
  groupData: groupData
21274
21425
  }
21275
21426
  }, /*#__PURE__*/React.createElement(View$2, {
21276
- "data-testid": "group-container"
21427
+ testID: "group-container"
21277
21428
  }, /*#__PURE__*/React.createElement(GroupSections, null)));
21278
21429
  };
21279
21430
 
@@ -21555,7 +21706,7 @@ var PointsTileFormattedPoints = function () {
21555
21706
  var fullPointsText = "".concat(pointsPrefix).concat(calculatedPoints, " ").concat(pointsSuffix).trim();
21556
21707
  return /*#__PURE__*/React.createElement(View$2, {
21557
21708
  testID: "points-tile-points",
21558
- accessibilityRole: "text",
21709
+ role: "article",
21559
21710
  accessibilityLabel: "Points value: ".concat(fullPointsText)
21560
21711
  }, /*#__PURE__*/React.createElement(Row, {
21561
21712
  align: "center",
@@ -21591,7 +21742,7 @@ var PointsTileMedia = function (_a) {
21591
21742
  return /*#__PURE__*/React.createElement(View$2, {
21592
21743
  testID: "points-tile-media",
21593
21744
  style: styles.imageContainer,
21594
- accessibilityRole: "image",
21745
+ role: "img",
21595
21746
  accessibilityLabel: "Points tile image for ".concat(title)
21596
21747
  }, /*#__PURE__*/React.createElement(Image$2, {
21597
21748
  source: {
@@ -21615,7 +21766,7 @@ var PointsTileTitle = function () {
21615
21766
  return /*#__PURE__*/React.createElement(Text, {
21616
21767
  variant: "eyebrow",
21617
21768
  testID: "points-tile-title",
21618
- accessibilityRole: "header",
21769
+ role: "heading",
21619
21770
  accessibilityLabel: title
21620
21771
  }, title);
21621
21772
  };
@@ -21713,7 +21864,7 @@ var RewardCategoryHeader = function () {
21713
21864
  backgroundColor: theme.primary
21714
21865
  }],
21715
21866
  testID: "reward-category-header",
21716
- accessibilityRole: "header",
21867
+ role: "heading",
21717
21868
  accessibilityLabel: "Reward category: ".concat(name)
21718
21869
  }, /*#__PURE__*/React.createElement(Text, {
21719
21870
  style: [styles.headerText, {
@@ -21745,7 +21896,7 @@ var RewardCategoryMedia = function () {
21745
21896
  },
21746
21897
  style: styles.background,
21747
21898
  alt: "Reward category image for ".concat(name),
21748
- accessibilityRole: "image"
21899
+ role: "img"
21749
21900
  });
21750
21901
  };
21751
21902
 
@@ -21784,7 +21935,7 @@ var RewardTileChevron = function () {
21784
21935
  name: "ChevronRight",
21785
21936
  size: IS_MOBILE ? 16 : undefined,
21786
21937
  color: ((_a = theme === null || theme === void 0 ? void 0 : theme.derivedSurfaceText) === null || _a === void 0 ? void 0 : _a[20]) || '#000000',
21787
- accessibilityRole: "image",
21938
+ role: "img",
21788
21939
  accessibilityLabel: "View reward details"
21789
21940
  });
21790
21941
  };
@@ -21868,7 +22019,7 @@ var RewardTileMedia = function (_a) {
21868
22019
  return /*#__PURE__*/React.createElement(View$2, {
21869
22020
  style: [styles.imageContainer, containerStyle],
21870
22021
  testID: "reward-tile-media",
21871
- accessibilityRole: "image",
22022
+ role: "img",
21872
22023
  accessibilityLabel: "Reward image for ".concat(name)
21873
22024
  }, /*#__PURE__*/React.createElement(ProgressiveImage, {
21874
22025
  source: {
@@ -21904,7 +22055,7 @@ var RewardTilePoints = function () {
21904
22055
  var accessibilityLabel = getPointsLabel('Reward points:', calculatedPoints, pointsPrefix, pointsSuffix);
21905
22056
  return /*#__PURE__*/React.createElement(View$2, {
21906
22057
  testID: "reward-tile-points",
21907
- accessibilityRole: "text",
22058
+ role: "article",
21908
22059
  accessibilityLabel: accessibilityLabel
21909
22060
  }, /*#__PURE__*/React.createElement(Row, {
21910
22061
  align: "center",
@@ -21935,7 +22086,7 @@ var RewardTileSummary = function () {
21935
22086
  if (!summary) return null;
21936
22087
  return /*#__PURE__*/React.createElement(Text, {
21937
22088
  variant: "body",
21938
- accessibilityRole: "text",
22089
+ role: "article",
21939
22090
  accessibilityLabel: summary,
21940
22091
  testID: "reward-tile-summary"
21941
22092
  }, summary);
@@ -21961,7 +22112,7 @@ var RewardTileTitle = function () {
21961
22112
  variant: "title",
21962
22113
  ellipsizeMode: "tail",
21963
22114
  numberOfLines: 1,
21964
- accessibilityRole: "header",
22115
+ role: "heading",
21965
22116
  accessibilityLabel: "Reward title: ".concat(name),
21966
22117
  testID: "reward-tile-title",
21967
22118
  style: handleTitleWidth()