@tapcart/mobile-components 0.12.21 → 0.13.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.
@@ -0,0 +1,74 @@
1
+ export type PersonalizedClusterFeedFrame = {
2
+ bundleId?: string | number | null;
3
+ layoutType?: string | null;
4
+ collectionId?: string | number | null;
5
+ anchorProductId?: string | number | null;
6
+ complementProductIds?: Array<string | number>;
7
+ title?: string | null;
8
+ hook?: string | null;
9
+ theme?: string | null;
10
+ atcScore?: number | null;
11
+ content?: {
12
+ contentType?: string | null;
13
+ contentUrl?: string | null;
14
+ } | null;
15
+ [key: string]: unknown;
16
+ };
17
+ export type PersonalizedClusterFeedData = {
18
+ collectionIds: string[];
19
+ explanations: Record<string, unknown>;
20
+ frames: PersonalizedClusterFeedFrame[];
21
+ };
22
+ export type PersonalizedClusterFeedStatus = "idle" | "loading" | "ready" | "empty" | "error";
23
+ export type UsePersonalizedClusterFeedProps = {
24
+ appId?: string | null;
25
+ deviceId?: string | null;
26
+ customerProfilesBaseUrl?: string | null;
27
+ customerProfilesBaseURL?: string | null;
28
+ dashboardPreview?: boolean;
29
+ skip?: boolean;
30
+ };
31
+ export type UsePersonalizedClusterFeedResult = {
32
+ data: PersonalizedClusterFeedData | null;
33
+ status: PersonalizedClusterFeedStatus;
34
+ error: unknown;
35
+ isLoading: boolean;
36
+ };
37
+ export declare const normalizePersonalizedClusterFeedBaseUrl: (value?: string | null) => string | null;
38
+ export declare const createPersonalizedClusterFeedRequestKey: ({ appId, deviceId, customerProfilesBaseUrl, dashboardPreview, }: {
39
+ appId: string;
40
+ deviceId?: string | null | undefined;
41
+ customerProfilesBaseUrl: string;
42
+ dashboardPreview?: boolean | undefined;
43
+ }) => string;
44
+ export declare const getPersonalizedClusterFeedSessionCacheKey: (appId: string, deviceId: string) => string;
45
+ export declare const normalizePersonalizedClusterFeed: (data: unknown) => PersonalizedClusterFeedData;
46
+ export declare const isEmptyPersonalizedClusterFeed: (data: PersonalizedClusterFeedData | null) => boolean;
47
+ export declare const readPersonalizedClusterFeedSessionCache: ({ appId, deviceId, freshMs, swrMs, }: {
48
+ appId: string;
49
+ deviceId: string;
50
+ freshMs: number;
51
+ swrMs: number;
52
+ }) => {
53
+ data: PersonalizedClusterFeedData;
54
+ fresh: boolean;
55
+ } | null;
56
+ export declare const writePersonalizedClusterFeedSessionCache: ({ appId, deviceId, data, }: {
57
+ appId: string;
58
+ deviceId: string;
59
+ data: PersonalizedClusterFeedData;
60
+ }) => void;
61
+ export declare function fetchPersonalizedClusterFeed({ appId, deviceId, customerProfilesBaseUrl, dashboardPreview, signal, }: {
62
+ appId: string;
63
+ deviceId?: string | null;
64
+ customerProfilesBaseUrl: string;
65
+ dashboardPreview?: boolean;
66
+ signal?: AbortSignal;
67
+ }): Promise<PersonalizedClusterFeedData>;
68
+ export declare const fetchPersonalizedClusterFeedOnce: ({ requests, key, fetcher, retentionMs, }: {
69
+ requests: Map<string, Promise<PersonalizedClusterFeedData>>;
70
+ key: string;
71
+ fetcher: () => Promise<PersonalizedClusterFeedData>;
72
+ retentionMs?: number | undefined;
73
+ }) => Promise<PersonalizedClusterFeedData>;
74
+ //# sourceMappingURL=use-personalized-cluster-feed-core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-personalized-cluster-feed-core.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-personalized-cluster-feed-core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,163 @@
1
+ "use client";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ const isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
12
+ const normalizeStringIds = (ids) => Array.isArray(ids)
13
+ ? ids.filter((id) => id != null).map((id) => String(id))
14
+ : [];
15
+ const normalizeFrame = (frame) => {
16
+ if (!isRecord(frame))
17
+ return null;
18
+ return Object.assign(Object.assign(Object.assign({}, frame), (frame.layoutType != null
19
+ ? { layoutType: String(frame.layoutType) }
20
+ : {})), (Array.isArray(frame.complementProductIds)
21
+ ? {
22
+ complementProductIds: frame.complementProductIds
23
+ .filter((id) => id != null)
24
+ .map((id) => String(id)),
25
+ }
26
+ : {}));
27
+ };
28
+ export const normalizePersonalizedClusterFeedBaseUrl = (value) => {
29
+ if (!value)
30
+ return null;
31
+ return String(value).replace(/\/+$/, "");
32
+ };
33
+ export const createPersonalizedClusterFeedRequestKey = ({ appId, deviceId, customerProfilesBaseUrl, dashboardPreview, }) => {
34
+ const mode = dashboardPreview ? "preview" : "cluster-feed";
35
+ return [
36
+ "personalized-cluster-feed",
37
+ mode,
38
+ normalizePersonalizedClusterFeedBaseUrl(customerProfilesBaseUrl),
39
+ appId,
40
+ dashboardPreview ? "preview" : deviceId,
41
+ ].join(":");
42
+ };
43
+ export const getPersonalizedClusterFeedSessionCacheKey = (appId, deviceId) => `foryou-cluster-${appId}-${deviceId}`;
44
+ export const normalizePersonalizedClusterFeed = (data) => {
45
+ const source = isRecord(data) ? data : {};
46
+ return {
47
+ collectionIds: normalizeStringIds(source.collectionIds),
48
+ explanations: isRecord(source.explanations) ? source.explanations : {},
49
+ frames: Array.isArray(source.frames)
50
+ ? source.frames
51
+ .map(normalizeFrame)
52
+ .filter((frame) => Boolean(frame))
53
+ : [],
54
+ };
55
+ };
56
+ export const isEmptyPersonalizedClusterFeed = (data) => Boolean(data) && !data.collectionIds.length && !data.frames.length;
57
+ export const readPersonalizedClusterFeedSessionCache = ({ appId, deviceId, freshMs, swrMs, }) => {
58
+ try {
59
+ const cached = sessionStorage.getItem(getPersonalizedClusterFeedSessionCacheKey(appId, deviceId));
60
+ if (!cached)
61
+ return null;
62
+ const { data, ts } = JSON.parse(cached);
63
+ const age = Date.now() - Number(ts || 0);
64
+ if (age >= swrMs)
65
+ return null;
66
+ return {
67
+ data: normalizePersonalizedClusterFeed(data),
68
+ fresh: age < freshMs,
69
+ };
70
+ }
71
+ catch (_a) {
72
+ return null;
73
+ }
74
+ };
75
+ export const writePersonalizedClusterFeedSessionCache = ({ appId, deviceId, data, }) => {
76
+ try {
77
+ sessionStorage.setItem(getPersonalizedClusterFeedSessionCacheKey(appId, deviceId), JSON.stringify({ data, ts: Date.now() }));
78
+ }
79
+ catch (_a) { }
80
+ };
81
+ function fetchWithTimeout(url, options = {}, timeoutMs = 15000) {
82
+ return __awaiter(this, void 0, void 0, function* () {
83
+ const controller = new AbortController();
84
+ const upstreamSignal = options === null || options === void 0 ? void 0 : options.signal;
85
+ const abortFromUpstream = () => controller.abort(upstreamSignal === null || upstreamSignal === void 0 ? void 0 : upstreamSignal.reason);
86
+ if (upstreamSignal === null || upstreamSignal === void 0 ? void 0 : upstreamSignal.aborted) {
87
+ controller.abort(upstreamSignal.reason);
88
+ }
89
+ else {
90
+ upstreamSignal === null || upstreamSignal === void 0 ? void 0 : upstreamSignal.addEventListener("abort", abortFromUpstream, { once: true });
91
+ }
92
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
93
+ try {
94
+ return yield fetch(url, Object.assign(Object.assign({}, options), { signal: controller.signal }));
95
+ }
96
+ finally {
97
+ upstreamSignal === null || upstreamSignal === void 0 ? void 0 : upstreamSignal.removeEventListener("abort", abortFromUpstream);
98
+ clearTimeout(timeoutId);
99
+ }
100
+ });
101
+ }
102
+ function readJson(response) {
103
+ return __awaiter(this, void 0, void 0, function* () {
104
+ try {
105
+ return yield response.json();
106
+ }
107
+ catch (error) {
108
+ const err = new Error((error === null || error === void 0 ? void 0 : error.message) || "Malformed JSON");
109
+ err.reason = "cluster-feed-parse";
110
+ throw err;
111
+ }
112
+ });
113
+ }
114
+ export function fetchPersonalizedClusterFeed({ appId, deviceId, customerProfilesBaseUrl, dashboardPreview, signal, }) {
115
+ var _a, _b, _c;
116
+ return __awaiter(this, void 0, void 0, function* () {
117
+ const baseUrl = normalizePersonalizedClusterFeedBaseUrl(customerProfilesBaseUrl);
118
+ const path = dashboardPreview
119
+ ? `/api/v1/personalized-feed/${encodeURIComponent(appId)}/clusters/preview`
120
+ : `/api/v1/personalized-feed/${encodeURIComponent(appId)}/${encodeURIComponent(String(deviceId))}/cluster-feed`;
121
+ const url = `${baseUrl}${path}`;
122
+ let response;
123
+ try {
124
+ response = yield fetchWithTimeout(url, { signal });
125
+ }
126
+ catch (error) {
127
+ const err = new Error((error === null || error === void 0 ? void 0 : error.message) || "Cluster feed request failed");
128
+ err.reason = "cluster-feed-network";
129
+ throw err;
130
+ }
131
+ if (!response.ok) {
132
+ const err = new Error(`Cluster feed HTTP ${response.status}`);
133
+ err.reason = "cluster-feed-http";
134
+ err.status = response.status;
135
+ err.retryAfter = (_c = (_b = (_a = response.headers) === null || _a === void 0 ? void 0 : _a.get) === null || _b === void 0 ? void 0 : _b.call(_a, "Retry-After")) !== null && _c !== void 0 ? _c : null;
136
+ throw err;
137
+ }
138
+ return normalizePersonalizedClusterFeed(yield readJson(response));
139
+ });
140
+ }
141
+ export const fetchPersonalizedClusterFeedOnce = ({ requests, key, fetcher, retentionMs = 0, }) => {
142
+ const existing = requests.get(key);
143
+ if (existing)
144
+ return existing;
145
+ const promise = fetcher();
146
+ requests.set(key, promise);
147
+ const release = () => {
148
+ if (requests.get(key) === promise) {
149
+ requests.delete(key);
150
+ }
151
+ };
152
+ const cleanup = () => {
153
+ var _a, _b;
154
+ if (retentionMs <= 0) {
155
+ release();
156
+ return;
157
+ }
158
+ const timeoutId = setTimeout(release, retentionMs);
159
+ (_b = (_a = timeoutId).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
160
+ };
161
+ promise.then(cleanup, cleanup);
162
+ return promise;
163
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=use-personalized-cluster-feed-core.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-personalized-cluster-feed-core.test.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-personalized-cluster-feed-core.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,106 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { createPersonalizedClusterFeedRequestKey, fetchPersonalizedClusterFeed, normalizePersonalizedClusterFeed, readPersonalizedClusterFeedSessionCache, writePersonalizedClusterFeedSessionCache, } from "./use-personalized-cluster-feed-core";
11
+ describe("personalized cluster feed core", () => {
12
+ beforeEach(() => {
13
+ sessionStorage.clear();
14
+ jest.restoreAllMocks();
15
+ global.fetch = jest.fn();
16
+ });
17
+ it("creates stable request keys for feed and preview modes", () => {
18
+ expect(createPersonalizedClusterFeedRequestKey({
19
+ appId: "app/id",
20
+ deviceId: "device/id",
21
+ customerProfilesBaseUrl: "https://profiles.test/",
22
+ })).toBe("personalized-cluster-feed:cluster-feed:https://profiles.test:app/id:device/id");
23
+ expect(createPersonalizedClusterFeedRequestKey({
24
+ appId: "app/id",
25
+ customerProfilesBaseUrl: "https://profiles.test/",
26
+ dashboardPreview: true,
27
+ })).toBe("personalized-cluster-feed:preview:https://profiles.test:app/id:preview");
28
+ });
29
+ it("normalizes payloads without adding absent frame fields", () => {
30
+ expect(normalizePersonalizedClusterFeed({
31
+ collectionIds: [123, "456", null],
32
+ explanations: "bad",
33
+ frames: [
34
+ { bundleId: "bundle-1", layoutType: 42 },
35
+ {
36
+ layoutType: "complete_the_look",
37
+ complementProductIds: [1, "2", null],
38
+ },
39
+ null,
40
+ ],
41
+ })).toEqual({
42
+ collectionIds: ["123", "456"],
43
+ explanations: {},
44
+ frames: [
45
+ { bundleId: "bundle-1", layoutType: "42" },
46
+ {
47
+ layoutType: "complete_the_look",
48
+ complementProductIds: ["1", "2"],
49
+ },
50
+ ],
51
+ });
52
+ });
53
+ it("round-trips session cache with freshness metadata", () => {
54
+ writePersonalizedClusterFeedSessionCache({
55
+ appId: "app-id",
56
+ deviceId: "device-id",
57
+ data: { collectionIds: ["1"], explanations: {}, frames: [] },
58
+ });
59
+ expect(readPersonalizedClusterFeedSessionCache({
60
+ appId: "app-id",
61
+ deviceId: "device-id",
62
+ freshMs: 1000,
63
+ swrMs: 2000,
64
+ })).toEqual({
65
+ data: { collectionIds: ["1"], explanations: {}, frames: [] },
66
+ fresh: true,
67
+ });
68
+ });
69
+ it("fetches cluster feed and preserves cluster-feed error reasons", () => __awaiter(void 0, void 0, void 0, function* () {
70
+ var _a;
71
+ const fetchMock = global.fetch
72
+ .mockResolvedValueOnce({
73
+ ok: true,
74
+ status: 200,
75
+ json: () => Promise.resolve({
76
+ collectionIds: ["1"],
77
+ explanations: {},
78
+ frames: [{ layoutType: "ranked_collection" }],
79
+ }),
80
+ })
81
+ .mockResolvedValueOnce({
82
+ ok: false,
83
+ status: 500,
84
+ headers: { get: () => "3" },
85
+ });
86
+ yield expect(fetchPersonalizedClusterFeed({
87
+ appId: "app/id",
88
+ deviceId: "device/id",
89
+ customerProfilesBaseUrl: "https://profiles.test/",
90
+ })).resolves.toEqual({
91
+ collectionIds: ["1"],
92
+ explanations: {},
93
+ frames: [{ layoutType: "ranked_collection" }],
94
+ });
95
+ expect((_a = fetchMock.mock.calls[0]) === null || _a === void 0 ? void 0 : _a[0]).toBe("https://profiles.test/api/v1/personalized-feed/app%2Fid/device%2Fid/cluster-feed");
96
+ yield expect(fetchPersonalizedClusterFeed({
97
+ appId: "app-id",
98
+ deviceId: "device-id",
99
+ customerProfilesBaseUrl: "https://profiles.test",
100
+ })).rejects.toMatchObject({
101
+ reason: "cluster-feed-http",
102
+ status: 500,
103
+ retryAfter: "3",
104
+ });
105
+ }));
106
+ });
@@ -0,0 +1,5 @@
1
+ import { type UsePersonalizedClusterFeedProps, type UsePersonalizedClusterFeedResult } from "./use-personalized-cluster-feed-core";
2
+ export type { PersonalizedClusterFeedData, PersonalizedClusterFeedFrame, PersonalizedClusterFeedStatus, UsePersonalizedClusterFeedProps, UsePersonalizedClusterFeedResult, } from "./use-personalized-cluster-feed-core";
3
+ export { createPersonalizedClusterFeedRequestKey, fetchPersonalizedClusterFeed, fetchPersonalizedClusterFeedOnce, isEmptyPersonalizedClusterFeed, normalizePersonalizedClusterFeed, normalizePersonalizedClusterFeedBaseUrl, readPersonalizedClusterFeedSessionCache, writePersonalizedClusterFeedSessionCache, } from "./use-personalized-cluster-feed-core";
4
+ export declare function usePersonalizedClusterFeed({ appId: rawAppId, deviceId: rawDeviceId, customerProfilesBaseUrl: rawCustomerProfilesBaseUrl, customerProfilesBaseURL, dashboardPreview, skip, }?: UsePersonalizedClusterFeedProps): UsePersonalizedClusterFeedResult;
5
+ //# sourceMappingURL=use-personalized-cluster-feed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-personalized-cluster-feed.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-personalized-cluster-feed.ts"],"names":[],"mappings":"AAIA,OAAO,EAUL,KAAK,+BAA+B,EACpC,KAAK,gCAAgC,EACtC,MAAM,sCAAsC,CAAA;AAE7C,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,EAC5B,6BAA6B,EAC7B,+BAA+B,EAC/B,gCAAgC,GACjC,MAAM,sCAAsC,CAAA;AAE7C,OAAO,EACL,uCAAuC,EACvC,4BAA4B,EAC5B,gCAAgC,EAChC,8BAA8B,EAC9B,gCAAgC,EAChC,uCAAuC,EACvC,uCAAuC,EACvC,wCAAwC,GACzC,MAAM,sCAAsC,CAAA;AAkE7C,wBAAgB,0BAA0B,CAAC,EACzC,KAAK,EAAE,QAAQ,EACf,QAAQ,EAAE,WAAW,EACrB,uBAAuB,EAAE,0BAA0B,EACnD,uBAAuB,EACvB,gBAAwB,EACxB,IAAY,GACb,GAAE,+BAAoC,GAAG,gCAAgC,CA2JzE"}
@@ -0,0 +1,191 @@
1
+ "use client";
2
+ import * as React from "react";
3
+ import { createPersonalizedClusterFeedRequestKey, fetchPersonalizedClusterFeed, fetchPersonalizedClusterFeedOnce, isEmptyPersonalizedClusterFeed, normalizePersonalizedClusterFeedBaseUrl, readPersonalizedClusterFeedSessionCache, writePersonalizedClusterFeedSessionCache, } from "./use-personalized-cluster-feed-core";
4
+ export { createPersonalizedClusterFeedRequestKey, fetchPersonalizedClusterFeed, fetchPersonalizedClusterFeedOnce, isEmptyPersonalizedClusterFeed, normalizePersonalizedClusterFeed, normalizePersonalizedClusterFeedBaseUrl, readPersonalizedClusterFeedSessionCache, writePersonalizedClusterFeedSessionCache, } from "./use-personalized-cluster-feed-core";
5
+ const FRESH_MS = 2 * 60 * 1000;
6
+ const SWR_MS = 30 * 60 * 1000;
7
+ const SINGLE_FLIGHT_RETENTION_MS = 5000;
8
+ const clusterFeedRequests = new Map();
9
+ const isEnabledDebugValue = (value) => ["1", "true", "yes", "on"].includes(String(value || "").toLowerCase());
10
+ const isPersonalizationDebugEnabled = () => {
11
+ var _a, _b;
12
+ if (typeof window === "undefined")
13
+ return false;
14
+ try {
15
+ const params = new URLSearchParams(((_a = window.location) === null || _a === void 0 ? void 0 : _a.search) || "");
16
+ if (isEnabledDebugValue(params.get("personalizationDebug")) ||
17
+ isEnabledDebugValue(params.get("debugPersonalization"))) {
18
+ return true;
19
+ }
20
+ }
21
+ catch (_c) { }
22
+ try {
23
+ return isEnabledDebugValue((_b = window.localStorage) === null || _b === void 0 ? void 0 : _b.getItem("personalizationDebug"));
24
+ }
25
+ catch (_d) {
26
+ return false;
27
+ }
28
+ };
29
+ const debugPersonalizationFallback = (event, context = {}) => {
30
+ if (!isPersonalizationDebugEnabled())
31
+ return;
32
+ // eslint-disable-next-line no-console
33
+ console.info(Object.assign({ message: "Personalized cluster feed package fallback", event }, context));
34
+ };
35
+ const summarizeClusterFeed = (data) => {
36
+ var _a, _b;
37
+ return ({
38
+ hasData: Boolean(data),
39
+ collectionCount: ((_a = data === null || data === void 0 ? void 0 : data.collectionIds) === null || _a === void 0 ? void 0 : _a.length) || 0,
40
+ frameCount: ((_b = data === null || data === void 0 ? void 0 : data.frames) === null || _b === void 0 ? void 0 : _b.length) || 0,
41
+ });
42
+ };
43
+ const summarizeClusterFeedError = (error) => error
44
+ ? {
45
+ reason: error.reason,
46
+ status: error.status,
47
+ message: error.message,
48
+ }
49
+ : null;
50
+ export function usePersonalizedClusterFeed({ appId: rawAppId, deviceId: rawDeviceId, customerProfilesBaseUrl: rawCustomerProfilesBaseUrl, customerProfilesBaseURL, dashboardPreview = false, skip = false, } = {}) {
51
+ const appId = rawAppId ? String(rawAppId) : "";
52
+ const deviceId = rawDeviceId ? String(rawDeviceId) : "";
53
+ const customerProfilesBaseUrl = normalizePersonalizedClusterFeedBaseUrl(rawCustomerProfilesBaseUrl || customerProfilesBaseURL);
54
+ const shouldSkip = Boolean(skip ||
55
+ !appId ||
56
+ !customerProfilesBaseUrl ||
57
+ (!dashboardPreview && !deviceId));
58
+ const requestKey = React.useMemo(() => {
59
+ if (shouldSkip)
60
+ return null;
61
+ return createPersonalizedClusterFeedRequestKey({
62
+ customerProfilesBaseUrl: customerProfilesBaseUrl,
63
+ appId,
64
+ deviceId,
65
+ dashboardPreview,
66
+ });
67
+ }, [appId, customerProfilesBaseUrl, dashboardPreview, deviceId, shouldSkip]);
68
+ const [data, setData] = React.useState(null);
69
+ const [error, setError] = React.useState(null);
70
+ const [isLoading, setIsLoading] = React.useState(false);
71
+ React.useEffect(() => {
72
+ debugPersonalizationFallback("effect", {
73
+ appId,
74
+ hasDeviceId: Boolean(deviceId),
75
+ hasCustomerProfilesBaseUrl: Boolean(customerProfilesBaseUrl),
76
+ dashboardPreview,
77
+ skip,
78
+ shouldSkip,
79
+ requestKey,
80
+ });
81
+ if (shouldSkip || !requestKey) {
82
+ setData(null);
83
+ setError(null);
84
+ setIsLoading(false);
85
+ return;
86
+ }
87
+ let cancelled = false;
88
+ setError(null);
89
+ const cached = !dashboardPreview && deviceId
90
+ ? readPersonalizedClusterFeedSessionCache({
91
+ appId,
92
+ deviceId,
93
+ freshMs: FRESH_MS,
94
+ swrMs: SWR_MS,
95
+ })
96
+ : null;
97
+ debugPersonalizationFallback("session-cache-result", {
98
+ appId,
99
+ cacheHit: Boolean(cached),
100
+ fresh: Boolean(cached === null || cached === void 0 ? void 0 : cached.fresh),
101
+ feed: summarizeClusterFeed(cached === null || cached === void 0 ? void 0 : cached.data),
102
+ });
103
+ if (cached) {
104
+ setData(cached.data);
105
+ if (cached.fresh) {
106
+ setIsLoading(false);
107
+ return;
108
+ }
109
+ }
110
+ else {
111
+ setData(null);
112
+ }
113
+ setIsLoading(!cached);
114
+ debugPersonalizationFallback("fetch-start", {
115
+ appId,
116
+ hasDeviceId: Boolean(deviceId),
117
+ dashboardPreview,
118
+ requestKey,
119
+ });
120
+ fetchPersonalizedClusterFeedOnce({
121
+ requests: clusterFeedRequests,
122
+ key: requestKey,
123
+ retentionMs: SINGLE_FLIGHT_RETENTION_MS,
124
+ fetcher: () => fetchPersonalizedClusterFeed({
125
+ appId,
126
+ deviceId,
127
+ customerProfilesBaseUrl: customerProfilesBaseUrl,
128
+ dashboardPreview,
129
+ }),
130
+ })
131
+ .then((result) => {
132
+ if (cancelled)
133
+ return;
134
+ if (!dashboardPreview && deviceId) {
135
+ writePersonalizedClusterFeedSessionCache({
136
+ appId,
137
+ deviceId,
138
+ data: result,
139
+ });
140
+ }
141
+ debugPersonalizationFallback("fetch-success", {
142
+ appId,
143
+ dashboardPreview,
144
+ feed: summarizeClusterFeed(result),
145
+ });
146
+ setData(result);
147
+ setIsLoading(false);
148
+ })
149
+ .catch((err) => {
150
+ if (cancelled)
151
+ return;
152
+ debugPersonalizationFallback("fetch-error", {
153
+ appId,
154
+ dashboardPreview,
155
+ error: summarizeClusterFeedError(err),
156
+ });
157
+ setError(err);
158
+ setIsLoading(false);
159
+ });
160
+ return () => {
161
+ cancelled = true;
162
+ };
163
+ }, [
164
+ appId,
165
+ customerProfilesBaseUrl,
166
+ dashboardPreview,
167
+ deviceId,
168
+ requestKey,
169
+ shouldSkip,
170
+ skip,
171
+ ]);
172
+ let status = "idle";
173
+ if (shouldSkip) {
174
+ status = "idle";
175
+ }
176
+ else if (data) {
177
+ status = isEmptyPersonalizedClusterFeed(data) ? "empty" : "ready";
178
+ }
179
+ else if (error) {
180
+ status = "error";
181
+ }
182
+ else if (isLoading) {
183
+ status = "loading";
184
+ }
185
+ return {
186
+ data,
187
+ status,
188
+ error,
189
+ isLoading,
190
+ };
191
+ }
package/dist/index.d.ts CHANGED
@@ -10,6 +10,7 @@ export * from "./components/hooks/swr-retry";
10
10
  export * from "./components/hooks/use-infinite-wishlist";
11
11
  export * from "./components/hooks/use-recommendations";
12
12
  export * from "./components/hooks/use-products";
13
+ export * from "./components/hooks/use-personalized-cluster-feed";
13
14
  export * from "./components/hooks/use-order-details";
14
15
  export * from "./components/hooks/use-scroll-direction";
15
16
  export * from "./components/hooks/use-sort-filter";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ export * from "./components/hooks/swr-retry";
10
10
  export * from "./components/hooks/use-infinite-wishlist";
11
11
  export * from "./components/hooks/use-recommendations";
12
12
  export * from "./components/hooks/use-products";
13
+ export * from "./components/hooks/use-personalized-cluster-feed";
13
14
  export * from "./components/hooks/use-order-details";
14
15
  export * from "./components/hooks/use-scroll-direction";
15
16
  export * from "./components/hooks/use-sort-filter";
package/dist/styles.css CHANGED
@@ -717,9 +717,15 @@ video {
717
717
  left: 0px;
718
718
  right: 0px;
719
719
  }
720
+ .-bottom-1 {
721
+ bottom: -0.25rem;
722
+ }
720
723
  .-bottom-12 {
721
724
  bottom: -3rem;
722
725
  }
726
+ .-left-1 {
727
+ left: -0.25rem;
728
+ }
723
729
  .-left-12 {
724
730
  left: -3rem;
725
731
  }
@@ -741,6 +747,9 @@ video {
741
747
  .bottom-2 {
742
748
  bottom: 0.5rem;
743
749
  }
750
+ .bottom-3 {
751
+ bottom: 0.75rem;
752
+ }
744
753
  .bottom-4 {
745
754
  bottom: 1rem;
746
755
  }
@@ -831,6 +840,9 @@ video {
831
840
  .z-\[1\] {
832
841
  z-index: 1;
833
842
  }
843
+ .z-\[2\] {
844
+ z-index: 2;
845
+ }
834
846
  .z-\[30\] {
835
847
  z-index: 30;
836
848
  }
@@ -1015,6 +1027,9 @@ video {
1015
1027
  .mt-4 {
1016
1028
  margin-top: 1rem;
1017
1029
  }
1030
+ .mt-6 {
1031
+ margin-top: 1.5rem;
1032
+ }
1018
1033
  .mt-auto {
1019
1034
  margin-top: auto;
1020
1035
  }
@@ -1072,6 +1087,12 @@ video {
1072
1087
  .hidden {
1073
1088
  display: none;
1074
1089
  }
1090
+ .aspect-\[327\/280\] {
1091
+ aspect-ratio: 327/280;
1092
+ }
1093
+ .aspect-\[327\/316\] {
1094
+ aspect-ratio: 327/316;
1095
+ }
1075
1096
  .aspect-productImages {
1076
1097
  aspect-ratio: var(--productImage-aspectRatio);
1077
1098
  }
@@ -1120,6 +1141,9 @@ video {
1120
1141
  .h-3 {
1121
1142
  height: 0.75rem;
1122
1143
  }
1144
+ .h-3\.5 {
1145
+ height: 0.875rem;
1146
+ }
1123
1147
  .h-32 {
1124
1148
  height: 8rem;
1125
1149
  }
@@ -1241,9 +1265,15 @@ video {
1241
1265
  .min-h-\[210px\] {
1242
1266
  min-height: 210px;
1243
1267
  }
1268
+ .min-h-\[230px\] {
1269
+ min-height: 230px;
1270
+ }
1244
1271
  .min-h-\[24px\] {
1245
1272
  min-height: 24px;
1246
1273
  }
1274
+ .min-h-\[260px\] {
1275
+ min-height: 260px;
1276
+ }
1247
1277
  .min-h-\[36px\] {
1248
1278
  min-height: 36px;
1249
1279
  }
@@ -1289,6 +1319,9 @@ video {
1289
1319
  .w-11 {
1290
1320
  width: 2.75rem;
1291
1321
  }
1322
+ .w-11\/12 {
1323
+ width: 91.666667%;
1324
+ }
1292
1325
  .w-12 {
1293
1326
  width: 3rem;
1294
1327
  }
@@ -1352,9 +1385,18 @@ video {
1352
1385
  .w-\[120\%\] {
1353
1386
  width: 120%;
1354
1387
  }
1388
+ .w-\[120px\] {
1389
+ width: 120px;
1390
+ }
1391
+ .w-\[132px\] {
1392
+ width: 132px;
1393
+ }
1355
1394
  .w-\[138px\] {
1356
1395
  width: 138px;
1357
1396
  }
1397
+ .w-\[140px\] {
1398
+ width: 140px;
1399
+ }
1358
1400
  .w-\[180px\] {
1359
1401
  width: 180px;
1360
1402
  }
@@ -1385,6 +1427,9 @@ video {
1385
1427
  .w-\[65\%\] {
1386
1428
  width: 65%;
1387
1429
  }
1430
+ .w-\[85\%\] {
1431
+ width: 85%;
1432
+ }
1388
1433
  .w-\[calc\(100\%-2rem\)\] {
1389
1434
  width: calc(100% - 2rem);
1390
1435
  }
@@ -1420,6 +1465,12 @@ video {
1420
1465
  .min-w-8 {
1421
1466
  min-width: 2rem;
1422
1467
  }
1468
+ .min-w-\[150px\] {
1469
+ min-width: 150px;
1470
+ }
1471
+ .min-w-\[53px\] {
1472
+ min-width: 53px;
1473
+ }
1423
1474
  .min-w-\[8rem\] {
1424
1475
  min-width: 8rem;
1425
1476
  }
@@ -1436,12 +1487,27 @@ video {
1436
1487
  .max-w-\[198px\] {
1437
1488
  max-width: 198px;
1438
1489
  }
1490
+ .max-w-\[220px\] {
1491
+ max-width: 220px;
1492
+ }
1493
+ .max-w-\[360px\] {
1494
+ max-width: 360px;
1495
+ }
1496
+ .max-w-\[480px\] {
1497
+ max-width: 480px;
1498
+ }
1499
+ .max-w-\[50\%\] {
1500
+ max-width: 50%;
1501
+ }
1439
1502
  .max-w-\[5rem\] {
1440
1503
  max-width: 5rem;
1441
1504
  }
1442
1505
  .max-w-\[75\%\] {
1443
1506
  max-width: 75%;
1444
1507
  }
1508
+ .max-w-\[min\(100\%\2c 440px\)\] {
1509
+ max-width: min(100%,440px);
1510
+ }
1445
1511
  .max-w-full {
1446
1512
  max-width: 100%;
1447
1513
  }
@@ -1484,6 +1550,9 @@ video {
1484
1550
  .basis-\[300px\] {
1485
1551
  flex-basis: 300px;
1486
1552
  }
1553
+ .basis-\[88\%\] {
1554
+ flex-basis: 88%;
1555
+ }
1487
1556
  .basis-full {
1488
1557
  flex-basis: 100%;
1489
1558
  }
@@ -1559,6 +1628,16 @@ video {
1559
1628
  --tw-scale-y: 1.25;
1560
1629
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1561
1630
  }
1631
+ .scale-150 {
1632
+ --tw-scale-x: 1.5;
1633
+ --tw-scale-y: 1.5;
1634
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1635
+ }
1636
+ .scale-\[1\.2\] {
1637
+ --tw-scale-x: 1.2;
1638
+ --tw-scale-y: 1.2;
1639
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1640
+ }
1562
1641
  .transform {
1563
1642
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1564
1643
  }
@@ -2105,9 +2184,6 @@ video {
2105
2184
  --tw-bg-opacity: 1;
2106
2185
  background-color: rgb(253 255 218 / var(--tw-bg-opacity, 1));
2107
2186
  }
2108
- .bg-\[var\(--coreColors-pageColor\2c \#ffffff\)\] {
2109
- background-color: var(--coreColors-pageColor,#ffffff);
2110
- }
2111
2187
  .bg-\[var\(--stateColors-skeleton\)\] {
2112
2188
  background-color: var(--stateColors-skeleton);
2113
2189
  }
@@ -2425,6 +2501,9 @@ video {
2425
2501
  .pr-4 {
2426
2502
  padding-right: 1rem;
2427
2503
  }
2504
+ .pr-6 {
2505
+ padding-right: 1.5rem;
2506
+ }
2428
2507
  .pt-0 {
2429
2508
  padding-top: 0px;
2430
2509
  }
@@ -2814,9 +2893,15 @@ video {
2814
2893
  .opacity-50 {
2815
2894
  opacity: 0.5;
2816
2895
  }
2896
+ .opacity-60 {
2897
+ opacity: 0.6;
2898
+ }
2817
2899
  .opacity-70 {
2818
2900
  opacity: 0.7;
2819
2901
  }
2902
+ .opacity-\[0\.42\] {
2903
+ opacity: 0.42;
2904
+ }
2820
2905
  .shadow {
2821
2906
  --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
2822
2907
  --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
@@ -2827,6 +2912,11 @@ video {
2827
2912
  --tw-shadow-colored: 0 0 6px 0 var(--tw-shadow-color);
2828
2913
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
2829
2914
  }
2915
+ .shadow-\[0_2px_8px_rgba\(0\2c 0\2c 0\2c 0\.4\)\] {
2916
+ --tw-shadow: 0 2px 8px rgba(0,0,0,0.4);
2917
+ --tw-shadow-colored: 0 2px 8px var(--tw-shadow-color);
2918
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
2919
+ }
2830
2920
  .shadow-lg {
2831
2921
  --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
2832
2922
  --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
@@ -2909,6 +2999,14 @@ video {
2909
2999
  --tw-blur: blur(8px);
2910
3000
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
2911
3001
  }
3002
+ .blur-2xl {
3003
+ --tw-blur: blur(40px);
3004
+ filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
3005
+ }
3006
+ .brightness-75 {
3007
+ --tw-brightness: brightness(.75);
3008
+ filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
3009
+ }
2912
3010
  .drop-shadow {
2913
3011
  --tw-drop-shadow: drop-shadow(0 1px 2px rgb(0 0 0 / 0.1)) drop-shadow(0 1px 1px rgb(0 0 0 / 0.06));
2914
3012
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
@@ -2934,6 +3032,11 @@ video {
2934
3032
  -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
2935
3033
  backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
2936
3034
  }
3035
+ .backdrop-blur-md {
3036
+ --tw-backdrop-blur: blur(12px);
3037
+ -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
3038
+ backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
3039
+ }
2937
3040
  .transition {
2938
3041
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
2939
3042
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tapcart/mobile-components",
3
- "version": "0.12.21",
3
+ "version": "0.13.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "style": "dist/styles.css",