@wlloyalty/wll-react-sdk 1.0.101 → 1.0.103
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/dist/index.d.ts +10 -1
- package/dist/native.js +182 -56
- package/dist/native.js.map +1 -1
- package/dist/types/components/molecules/Carousel/Carousel.stories.d.ts +3 -0
- package/dist/types/components/molecules/Carousel/index.d.ts +2 -1
- package/dist/types/context/WllSdkContext.d.ts +3 -0
- package/dist/types/unit-tests/eventEmitter.spec.d.ts +1 -0
- package/dist/types/utils/eventEmitter.d.ts +44 -0
- package/dist/web.js +165 -29
- package/dist/web.js.map +1 -1
- package/package.json +1 -1
|
@@ -3,10 +3,13 @@ declare const _default: Meta;
|
|
|
3
3
|
export default _default;
|
|
4
4
|
export declare const Default: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactRenderer, {
|
|
5
5
|
section?: import("../../../types/section").TSection;
|
|
6
|
+
autoRotateInterval?: number;
|
|
6
7
|
}>;
|
|
7
8
|
export declare const SingleItem: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactRenderer, {
|
|
8
9
|
section?: import("../../../types/section").TSection;
|
|
10
|
+
autoRotateInterval?: number;
|
|
9
11
|
}>;
|
|
10
12
|
export declare const ManyItems: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactRenderer, {
|
|
11
13
|
section?: import("../../../types/section").TSection;
|
|
14
|
+
autoRotateInterval?: number;
|
|
12
15
|
}>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TSection } from '../../../types/section';
|
|
2
2
|
type CarouselProps = {
|
|
3
3
|
section?: TSection;
|
|
4
|
+
autoRotateInterval?: number;
|
|
4
5
|
};
|
|
5
|
-
declare const Carousel: ({ section }: CarouselProps) => JSX.Element | null;
|
|
6
|
+
declare const Carousel: ({ section, autoRotateInterval, }: CarouselProps) => JSX.Element | null;
|
|
6
7
|
export default Carousel;
|
|
@@ -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
|
}>;
|
|
@@ -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;
|
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));
|
|
@@ -20558,22 +20628,24 @@ var carouselReducer = function (state, action) {
|
|
|
20558
20628
|
}
|
|
20559
20629
|
};
|
|
20560
20630
|
var Carousel = function (_a) {
|
|
20561
|
-
var section = _a.section
|
|
20631
|
+
var section = _a.section,
|
|
20632
|
+
_b = _a.autoRotateInterval,
|
|
20633
|
+
autoRotateInterval = _b === void 0 ? 5000 : _b;
|
|
20562
20634
|
if (!section) return null;
|
|
20563
20635
|
var WINDOW_WIDTH = useWindowDimensions().width;
|
|
20564
20636
|
var containerRef = React.useRef(null);
|
|
20565
20637
|
var styles = useCarouselStyles(BUTTON_SIZE);
|
|
20566
20638
|
var animatedIndex = React.useRef(new Animated$1.Value(0)).current;
|
|
20567
20639
|
var theme = useWllSdk().theme;
|
|
20568
|
-
var
|
|
20569
|
-
isDesktop =
|
|
20570
|
-
isTablet =
|
|
20640
|
+
var _c = useResponsive(),
|
|
20641
|
+
isDesktop = _c.isDesktop,
|
|
20642
|
+
isTablet = _c.isTablet;
|
|
20571
20643
|
var scrollViewRef = React.useRef(null);
|
|
20572
|
-
var
|
|
20644
|
+
var _d = React.useReducer(carouselReducer, __assign(__assign({}, initialState), {
|
|
20573
20645
|
containerWidth: WINDOW_WIDTH
|
|
20574
20646
|
})),
|
|
20575
|
-
state =
|
|
20576
|
-
dispatch =
|
|
20647
|
+
state = _d[0],
|
|
20648
|
+
dispatch = _d[1];
|
|
20577
20649
|
var currentIndex = state.currentIndex,
|
|
20578
20650
|
containerWidth = state.containerWidth;
|
|
20579
20651
|
var sortedTiles = sortByPriority(section.tiles.filter(function (tile) {
|
|
@@ -20604,15 +20676,40 @@ var Carousel = function (_a) {
|
|
|
20604
20676
|
};
|
|
20605
20677
|
var handleNext = function () {
|
|
20606
20678
|
var _a;
|
|
20679
|
+
var nextIndex = Math.min(sortedTiles.length - 1, currentIndex + 1);
|
|
20607
20680
|
dispatch({
|
|
20608
20681
|
type: 'NEXT_SLIDE',
|
|
20609
20682
|
maxIndex: sortedTiles.length - 1
|
|
20610
20683
|
});
|
|
20611
20684
|
(_a = scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo({
|
|
20612
|
-
x:
|
|
20685
|
+
x: nextIndex * containerWidth,
|
|
20613
20686
|
animated: true
|
|
20614
20687
|
});
|
|
20615
20688
|
};
|
|
20689
|
+
var rotateToNextSlide = React.useCallback(function () {
|
|
20690
|
+
var _a;
|
|
20691
|
+
if (currentIndex >= sortedTiles.length - 1) {
|
|
20692
|
+
dispatch({
|
|
20693
|
+
type: 'SET_CURRENT_INDEX',
|
|
20694
|
+
payload: 0
|
|
20695
|
+
});
|
|
20696
|
+
(_a = scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo({
|
|
20697
|
+
x: 0,
|
|
20698
|
+
animated: true
|
|
20699
|
+
});
|
|
20700
|
+
} else {
|
|
20701
|
+
handleNext();
|
|
20702
|
+
}
|
|
20703
|
+
}, [currentIndex, containerWidth, sortedTiles.length]);
|
|
20704
|
+
React.useEffect(function () {
|
|
20705
|
+
if (sortedTiles.length <= 1) return;
|
|
20706
|
+
var rotationTimer = setInterval(function () {
|
|
20707
|
+
rotateToNextSlide();
|
|
20708
|
+
}, autoRotateInterval);
|
|
20709
|
+
return function () {
|
|
20710
|
+
return clearInterval(rotationTimer);
|
|
20711
|
+
};
|
|
20712
|
+
}, [rotateToNextSlide, autoRotateInterval, sortedTiles.length]);
|
|
20616
20713
|
var displayControls = sortedTiles.length > 1;
|
|
20617
20714
|
var showPrevButton = displayControls && currentIndex > 0;
|
|
20618
20715
|
var showNextButton = displayControls && currentIndex < sortedTiles.length - 1;
|
|
@@ -21080,6 +21177,14 @@ var useGroupContext = function () {
|
|
|
21080
21177
|
/**
|
|
21081
21178
|
* Custom hook to fetch and manage group data
|
|
21082
21179
|
*
|
|
21180
|
+
* This hook handles two distinct data fetching scenarios:
|
|
21181
|
+
* 1. Initial fetch: Shows loading state while first loading data
|
|
21182
|
+
* 2. Background refresh: Updates data silently without loading states
|
|
21183
|
+
*
|
|
21184
|
+
* The hook subscribes to GROUP_DATA_CHANGED events to refresh data
|
|
21185
|
+
* when notified by the host application, ensuring UI remains responsive
|
|
21186
|
+
* without showing loading indicators during refreshes.
|
|
21187
|
+
*
|
|
21083
21188
|
* @param {string} id - The ID of the group to fetch
|
|
21084
21189
|
* @returns {Object} Object containing group data, loading state, and any error
|
|
21085
21190
|
*/
|
|
@@ -21094,27 +21199,22 @@ var useGroupData = function (id) {
|
|
|
21094
21199
|
var _c = React.useState(true),
|
|
21095
21200
|
isLoading = _c[0],
|
|
21096
21201
|
setIsLoading = _c[1];
|
|
21097
|
-
var
|
|
21098
|
-
|
|
21099
|
-
|
|
21100
|
-
|
|
21101
|
-
|
|
21102
|
-
return __awaiter(void 0, __spreadArray([], args_1, true), void 0, function (showLoading) {
|
|
21202
|
+
var _d = React.useState(false),
|
|
21203
|
+
isInitialFetchDone = _d[0],
|
|
21204
|
+
setIsInitialFetchDone = _d[1];
|
|
21205
|
+
var initialFetch = React.useCallback(function () {
|
|
21206
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
21103
21207
|
var response, err_1;
|
|
21104
|
-
if (showLoading === void 0) {
|
|
21105
|
-
showLoading = true;
|
|
21106
|
-
}
|
|
21107
21208
|
return __generator(this, function (_a) {
|
|
21108
21209
|
switch (_a.label) {
|
|
21109
21210
|
case 0:
|
|
21110
21211
|
if (!id || !sdk || !sdk.getGroupByID) {
|
|
21111
21212
|
setError('Unable to fetch group data: invalid configuration');
|
|
21112
21213
|
setIsLoading(false);
|
|
21214
|
+
setIsInitialFetchDone(true);
|
|
21113
21215
|
return [2 /*return*/];
|
|
21114
21216
|
}
|
|
21115
|
-
|
|
21116
|
-
setIsLoading(true);
|
|
21117
|
-
}
|
|
21217
|
+
setIsLoading(true);
|
|
21118
21218
|
setError(null);
|
|
21119
21219
|
_a.label = 1;
|
|
21120
21220
|
case 1:
|
|
@@ -21134,9 +21234,8 @@ var useGroupData = function (id) {
|
|
|
21134
21234
|
console.error('Error fetching group:', err_1);
|
|
21135
21235
|
return [3 /*break*/, 5];
|
|
21136
21236
|
case 4:
|
|
21137
|
-
|
|
21138
|
-
|
|
21139
|
-
}
|
|
21237
|
+
setIsLoading(false);
|
|
21238
|
+
setIsInitialFetchDone(true);
|
|
21140
21239
|
return [7 /*endfinally*/];
|
|
21141
21240
|
case 5:
|
|
21142
21241
|
return [2 /*return*/];
|
|
@@ -21144,12 +21243,49 @@ var useGroupData = function (id) {
|
|
|
21144
21243
|
});
|
|
21145
21244
|
});
|
|
21146
21245
|
}, [id, sdk]);
|
|
21246
|
+
var silentRefresh = React.useCallback(function () {
|
|
21247
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
21248
|
+
var response, err_2;
|
|
21249
|
+
return __generator(this, function (_a) {
|
|
21250
|
+
switch (_a.label) {
|
|
21251
|
+
case 0:
|
|
21252
|
+
if (!id || !sdk || !sdk.getGroupByID || !isInitialFetchDone) {
|
|
21253
|
+
return [2 /*return*/];
|
|
21254
|
+
}
|
|
21255
|
+
_a.label = 1;
|
|
21256
|
+
case 1:
|
|
21257
|
+
_a.trys.push([1, 3,, 4]);
|
|
21258
|
+
return [4 /*yield*/, sdk.refreshGroup(id)];
|
|
21259
|
+
case 2:
|
|
21260
|
+
response = _a.sent();
|
|
21261
|
+
if (response && response.status === 'success' && response.data) {
|
|
21262
|
+
setGroupData(response.data);
|
|
21263
|
+
}
|
|
21264
|
+
return [3 /*break*/, 4];
|
|
21265
|
+
case 3:
|
|
21266
|
+
err_2 = _a.sent();
|
|
21267
|
+
console.error('Error during silent refresh:', err_2);
|
|
21268
|
+
return [3 /*break*/, 4];
|
|
21269
|
+
case 4:
|
|
21270
|
+
return [2 /*return*/];
|
|
21271
|
+
}
|
|
21272
|
+
});
|
|
21273
|
+
});
|
|
21274
|
+
}, [id, sdk, isInitialFetchDone]);
|
|
21147
21275
|
var refreshGroup = React.useCallback(function () {
|
|
21148
|
-
return
|
|
21149
|
-
}, [
|
|
21276
|
+
return silentRefresh();
|
|
21277
|
+
}, [silentRefresh]);
|
|
21150
21278
|
React.useEffect(function () {
|
|
21151
|
-
|
|
21152
|
-
|
|
21279
|
+
if (sdk) {
|
|
21280
|
+
initialFetch();
|
|
21281
|
+
var unsubscribeGroup_1 = sdk.subscribeToDataChange('GROUP_DATA_CHANGED', function () {
|
|
21282
|
+
silentRefresh();
|
|
21283
|
+
});
|
|
21284
|
+
return function () {
|
|
21285
|
+
unsubscribeGroup_1();
|
|
21286
|
+
};
|
|
21287
|
+
}
|
|
21288
|
+
}, [initialFetch, id, sdk, silentRefresh]);
|
|
21153
21289
|
return {
|
|
21154
21290
|
groupData: groupData,
|
|
21155
21291
|
isLoading: isLoading,
|
|
@@ -21246,7 +21382,7 @@ var Group = function (_a) {
|
|
|
21246
21382
|
groupData: groupData
|
|
21247
21383
|
}
|
|
21248
21384
|
}, /*#__PURE__*/React.createElement(View$2, {
|
|
21249
|
-
|
|
21385
|
+
testID: "group-container"
|
|
21250
21386
|
}, /*#__PURE__*/React.createElement(GroupSections, null)));
|
|
21251
21387
|
};
|
|
21252
21388
|
|