@windrun-huaiin/third-ui 31.3.5 → 31.3.6

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.
@@ -1,5 +1,6 @@
1
1
  import { type CreditOverviewTranslations } from './credit-overview-client';
2
2
  import type { CreditOverviewData } from './types';
3
+ export declare const DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT = "windrun-huaiin:credit-overview:refresh";
3
4
  export interface CreditOverviewPayload {
4
5
  data: CreditOverviewData;
5
6
  totalLabel: string;
@@ -8,5 +9,19 @@ export interface CreditOverviewPayload {
8
9
  export interface CreditOverviewNavClientProps {
9
10
  locale: string;
10
11
  endpoint: string;
12
+ /**
13
+ * Browser event names that should trigger credit overview reload.
14
+ * Business apps can dispatch these events after credit balance changes.
15
+ *
16
+ * Default: ['windrun:credit-overview:refresh']
17
+ * Empty array means event listening is disabled.
18
+ */
19
+ refreshEvents?: string[];
20
+ /**
21
+ * Optional debounce for refresh event bursts.
22
+ * Default: 300ms.
23
+ */
24
+ refreshDebounceMs?: number;
11
25
  }
12
- export declare function CreditOverviewNavClient({ locale, endpoint, }: CreditOverviewNavClientProps): import("react/jsx-runtime").JSX.Element | null;
26
+ export declare function dispatchCreditOverviewRefresh(eventName?: string): void;
27
+ export declare function CreditOverviewNavClient({ locale, endpoint, refreshEvents, refreshDebounceMs, }: CreditOverviewNavClientProps): import("react/jsx-runtime").JSX.Element | null;
@@ -8,54 +8,114 @@ var React = require('react');
8
8
  var creditNavButton = require('./credit-nav-button.js');
9
9
  var creditOverviewClient = require('./credit-overview-client.js');
10
10
 
11
+ const DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT = 'windrun-huaiin:credit-overview:refresh';
11
12
  function buildCreditOverviewUrl(endpoint, locale) {
12
13
  const url = new URL(endpoint, window.location.origin);
13
14
  url.searchParams.set('locale', locale);
14
15
  return url.toString();
15
16
  }
16
- function CreditOverviewNavClient({ locale, endpoint, }) {
17
+ function normalizeRefreshEvents(refreshEvents) {
18
+ const events = refreshEvents !== null && refreshEvents !== void 0 ? refreshEvents : [DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT];
19
+ return Array.from(new Set(events
20
+ .map((eventName) => eventName.trim())
21
+ .filter((eventName) => eventName.length > 0)));
22
+ }
23
+ function buildRefreshEventsKey(refreshEvents) {
24
+ return normalizeRefreshEvents(refreshEvents).join('\n');
25
+ }
26
+ function dispatchCreditOverviewRefresh(eventName = DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT) {
27
+ if (typeof window === 'undefined') {
28
+ return;
29
+ }
30
+ window.dispatchEvent(new CustomEvent(eventName));
31
+ }
32
+ function CreditOverviewNavClient({ locale, endpoint, refreshEvents, refreshDebounceMs = 300, }) {
17
33
  const { isLoaded, isSignedIn, userId } = nextjs.useAuth();
18
34
  const [payload, setPayload] = React.useState(null);
35
+ const abortControllerRef = React.useRef(null);
36
+ const isMountedRef = React.useRef(false);
37
+ const refreshEventsKey = buildRefreshEventsKey(refreshEvents);
38
+ const normalizedRefreshEvents = React.useMemo(() => refreshEventsKey.split('\n').filter(Boolean), [refreshEventsKey]);
19
39
  React.useEffect(() => {
40
+ isMountedRef.current = true;
41
+ return () => {
42
+ var _a;
43
+ isMountedRef.current = false;
44
+ (_a = abortControllerRef.current) === null || _a === void 0 ? void 0 : _a.abort();
45
+ };
46
+ }, []);
47
+ const loadCreditOverview = React.useCallback(() => tslib.__awaiter(this, void 0, void 0, function* () {
48
+ var _a;
49
+ (_a = abortControllerRef.current) === null || _a === void 0 ? void 0 : _a.abort();
50
+ const controller = new AbortController();
51
+ abortControllerRef.current = controller;
52
+ try {
53
+ const response = yield fetch(buildCreditOverviewUrl(endpoint, locale), {
54
+ cache: 'no-store',
55
+ credentials: 'same-origin',
56
+ signal: controller.signal,
57
+ });
58
+ if (!response.ok) {
59
+ if (!controller.signal.aborted && isMountedRef.current) {
60
+ setPayload(null);
61
+ }
62
+ return;
63
+ }
64
+ const nextPayload = (yield response.json());
65
+ if (!controller.signal.aborted && isMountedRef.current) {
66
+ setPayload(nextPayload);
67
+ }
68
+ }
69
+ catch (error) {
70
+ if (!controller.signal.aborted && isMountedRef.current) {
71
+ setPayload(null);
72
+ console.warn('[CreditOverviewNavClient] Failed to load credit overview', error);
73
+ }
74
+ }
75
+ finally {
76
+ if (abortControllerRef.current === controller) {
77
+ abortControllerRef.current = null;
78
+ }
79
+ }
80
+ }), [endpoint, locale]);
81
+ React.useEffect(() => {
82
+ var _a;
20
83
  if (!isLoaded) {
21
84
  return;
22
85
  }
23
86
  if (!isSignedIn) {
87
+ (_a = abortControllerRef.current) === null || _a === void 0 ? void 0 : _a.abort();
88
+ abortControllerRef.current = null;
24
89
  setPayload(null);
25
90
  return;
26
91
  }
27
- const controller = new AbortController();
28
- function loadCreditOverview() {
29
- return tslib.__awaiter(this, void 0, void 0, function* () {
30
- try {
31
- const response = yield fetch(buildCreditOverviewUrl(endpoint, locale), {
32
- credentials: 'same-origin',
33
- signal: controller.signal,
34
- });
35
- if (!response.ok) {
36
- if (!controller.signal.aborted) {
37
- setPayload(null);
38
- }
39
- return;
40
- }
41
- const nextPayload = (yield response.json());
42
- if (!controller.signal.aborted) {
43
- setPayload(nextPayload);
44
- }
45
- }
46
- catch (error) {
47
- if (!controller.signal.aborted) {
48
- setPayload(null);
49
- console.warn('[CreditOverviewNavClient] Failed to load credit overview', error);
50
- }
51
- }
52
- });
92
+ void loadCreditOverview();
93
+ }, [isLoaded, isSignedIn, loadCreditOverview, userId]);
94
+ React.useEffect(() => {
95
+ if (!isLoaded || !isSignedIn || normalizedRefreshEvents.length === 0) {
96
+ return;
97
+ }
98
+ let debounceTimer = null;
99
+ const refresh = () => {
100
+ if (debounceTimer) {
101
+ window.clearTimeout(debounceTimer);
102
+ }
103
+ debounceTimer = window.setTimeout(() => {
104
+ void loadCreditOverview();
105
+ }, refreshDebounceMs);
106
+ };
107
+ for (const eventName of normalizedRefreshEvents) {
108
+ window.addEventListener(eventName, refresh);
53
109
  }
54
- loadCreditOverview();
55
110
  return () => {
56
- controller.abort();
111
+ if (debounceTimer) {
112
+ window.clearTimeout(debounceTimer);
113
+ }
114
+ for (const eventName of normalizedRefreshEvents) {
115
+ window.removeEventListener(eventName, refresh);
116
+ }
57
117
  };
58
- }, [endpoint, isLoaded, isSignedIn, locale, userId]);
118
+ }, [isLoaded, isSignedIn, loadCreditOverview, normalizedRefreshEvents, refreshDebounceMs]);
59
119
  if (!payload) {
60
120
  return null;
61
121
  }
@@ -63,3 +123,5 @@ function CreditOverviewNavClient({ locale, endpoint, }) {
63
123
  }
64
124
 
65
125
  exports.CreditOverviewNavClient = CreditOverviewNavClient;
126
+ exports.DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT = DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT;
127
+ exports.dispatchCreditOverviewRefresh = dispatchCreditOverviewRefresh;
@@ -2,62 +2,122 @@
2
2
  import { __awaiter } from 'tslib';
3
3
  import { jsx } from 'react/jsx-runtime';
4
4
  import { useAuth } from '@clerk/nextjs';
5
- import { useState, useEffect } from 'react';
5
+ import { useState, useRef, useMemo, useEffect, useCallback } from 'react';
6
6
  import { CreditNavButton } from './credit-nav-button.mjs';
7
7
  import { CreditOverviewClient } from './credit-overview-client.mjs';
8
8
 
9
+ const DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT = 'windrun-huaiin:credit-overview:refresh';
9
10
  function buildCreditOverviewUrl(endpoint, locale) {
10
11
  const url = new URL(endpoint, window.location.origin);
11
12
  url.searchParams.set('locale', locale);
12
13
  return url.toString();
13
14
  }
14
- function CreditOverviewNavClient({ locale, endpoint, }) {
15
+ function normalizeRefreshEvents(refreshEvents) {
16
+ const events = refreshEvents !== null && refreshEvents !== void 0 ? refreshEvents : [DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT];
17
+ return Array.from(new Set(events
18
+ .map((eventName) => eventName.trim())
19
+ .filter((eventName) => eventName.length > 0)));
20
+ }
21
+ function buildRefreshEventsKey(refreshEvents) {
22
+ return normalizeRefreshEvents(refreshEvents).join('\n');
23
+ }
24
+ function dispatchCreditOverviewRefresh(eventName = DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT) {
25
+ if (typeof window === 'undefined') {
26
+ return;
27
+ }
28
+ window.dispatchEvent(new CustomEvent(eventName));
29
+ }
30
+ function CreditOverviewNavClient({ locale, endpoint, refreshEvents, refreshDebounceMs = 300, }) {
15
31
  const { isLoaded, isSignedIn, userId } = useAuth();
16
32
  const [payload, setPayload] = useState(null);
33
+ const abortControllerRef = useRef(null);
34
+ const isMountedRef = useRef(false);
35
+ const refreshEventsKey = buildRefreshEventsKey(refreshEvents);
36
+ const normalizedRefreshEvents = useMemo(() => refreshEventsKey.split('\n').filter(Boolean), [refreshEventsKey]);
17
37
  useEffect(() => {
38
+ isMountedRef.current = true;
39
+ return () => {
40
+ var _a;
41
+ isMountedRef.current = false;
42
+ (_a = abortControllerRef.current) === null || _a === void 0 ? void 0 : _a.abort();
43
+ };
44
+ }, []);
45
+ const loadCreditOverview = useCallback(() => __awaiter(this, void 0, void 0, function* () {
46
+ var _a;
47
+ (_a = abortControllerRef.current) === null || _a === void 0 ? void 0 : _a.abort();
48
+ const controller = new AbortController();
49
+ abortControllerRef.current = controller;
50
+ try {
51
+ const response = yield fetch(buildCreditOverviewUrl(endpoint, locale), {
52
+ cache: 'no-store',
53
+ credentials: 'same-origin',
54
+ signal: controller.signal,
55
+ });
56
+ if (!response.ok) {
57
+ if (!controller.signal.aborted && isMountedRef.current) {
58
+ setPayload(null);
59
+ }
60
+ return;
61
+ }
62
+ const nextPayload = (yield response.json());
63
+ if (!controller.signal.aborted && isMountedRef.current) {
64
+ setPayload(nextPayload);
65
+ }
66
+ }
67
+ catch (error) {
68
+ if (!controller.signal.aborted && isMountedRef.current) {
69
+ setPayload(null);
70
+ console.warn('[CreditOverviewNavClient] Failed to load credit overview', error);
71
+ }
72
+ }
73
+ finally {
74
+ if (abortControllerRef.current === controller) {
75
+ abortControllerRef.current = null;
76
+ }
77
+ }
78
+ }), [endpoint, locale]);
79
+ useEffect(() => {
80
+ var _a;
18
81
  if (!isLoaded) {
19
82
  return;
20
83
  }
21
84
  if (!isSignedIn) {
85
+ (_a = abortControllerRef.current) === null || _a === void 0 ? void 0 : _a.abort();
86
+ abortControllerRef.current = null;
22
87
  setPayload(null);
23
88
  return;
24
89
  }
25
- const controller = new AbortController();
26
- function loadCreditOverview() {
27
- return __awaiter(this, void 0, void 0, function* () {
28
- try {
29
- const response = yield fetch(buildCreditOverviewUrl(endpoint, locale), {
30
- credentials: 'same-origin',
31
- signal: controller.signal,
32
- });
33
- if (!response.ok) {
34
- if (!controller.signal.aborted) {
35
- setPayload(null);
36
- }
37
- return;
38
- }
39
- const nextPayload = (yield response.json());
40
- if (!controller.signal.aborted) {
41
- setPayload(nextPayload);
42
- }
43
- }
44
- catch (error) {
45
- if (!controller.signal.aborted) {
46
- setPayload(null);
47
- console.warn('[CreditOverviewNavClient] Failed to load credit overview', error);
48
- }
49
- }
50
- });
90
+ void loadCreditOverview();
91
+ }, [isLoaded, isSignedIn, loadCreditOverview, userId]);
92
+ useEffect(() => {
93
+ if (!isLoaded || !isSignedIn || normalizedRefreshEvents.length === 0) {
94
+ return;
95
+ }
96
+ let debounceTimer = null;
97
+ const refresh = () => {
98
+ if (debounceTimer) {
99
+ window.clearTimeout(debounceTimer);
100
+ }
101
+ debounceTimer = window.setTimeout(() => {
102
+ void loadCreditOverview();
103
+ }, refreshDebounceMs);
104
+ };
105
+ for (const eventName of normalizedRefreshEvents) {
106
+ window.addEventListener(eventName, refresh);
51
107
  }
52
- loadCreditOverview();
53
108
  return () => {
54
- controller.abort();
109
+ if (debounceTimer) {
110
+ window.clearTimeout(debounceTimer);
111
+ }
112
+ for (const eventName of normalizedRefreshEvents) {
113
+ window.removeEventListener(eventName, refresh);
114
+ }
55
115
  };
56
- }, [endpoint, isLoaded, isSignedIn, locale, userId]);
116
+ }, [isLoaded, isSignedIn, loadCreditOverview, normalizedRefreshEvents, refreshDebounceMs]);
57
117
  if (!payload) {
58
118
  return null;
59
119
  }
60
120
  return (jsx(CreditNavButton, { locale: locale, totalBalance: payload.data.totalBalance, totalLabel: payload.totalLabel, children: jsx(CreditOverviewClient, { locale: locale, data: payload.data, translations: payload.translations }) }));
61
121
  }
62
122
 
63
- export { CreditOverviewNavClient };
123
+ export { CreditOverviewNavClient, DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT, dispatchCreditOverviewRefresh };
@@ -1,5 +1,5 @@
1
1
  export { CreditOverviewClient } from './credit-overview-client';
2
- export { CreditOverviewNavClient } from './credit-overview-nav-client';
2
+ export { CreditOverviewNavClient, DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT, dispatchCreditOverviewRefresh, } from './credit-overview-nav-client';
3
3
  export { CreditNavButton } from './credit-nav-button';
4
4
  export type { CreditOverviewTranslations } from './credit-overview-client';
5
5
  export type { CreditOverviewNavClientProps, CreditOverviewPayload, } from './credit-overview-nav-client';
@@ -9,4 +9,6 @@ var creditNavButton = require('./credit-nav-button.js');
9
9
 
10
10
  exports.CreditOverviewClient = creditOverviewClient.CreditOverviewClient;
11
11
  exports.CreditOverviewNavClient = creditOverviewNavClient.CreditOverviewNavClient;
12
+ exports.DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT = creditOverviewNavClient.DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT;
13
+ exports.dispatchCreditOverviewRefresh = creditOverviewNavClient.dispatchCreditOverviewRefresh;
12
14
  exports.CreditNavButton = creditNavButton.CreditNavButton;
@@ -1,4 +1,4 @@
1
1
  "use client";
2
2
  export { CreditOverviewClient } from './credit-overview-client.mjs';
3
- export { CreditOverviewNavClient } from './credit-overview-nav-client.mjs';
3
+ export { CreditOverviewNavClient, DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT, dispatchCreditOverviewRefresh } from './credit-overview-nav-client.mjs';
4
4
  export { CreditNavButton } from './credit-nav-button.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windrun-huaiin/third-ui",
3
- "version": "31.3.5",
3
+ "version": "31.3.6",
4
4
  "description": "Third-party integrated UI components for windrun-huaiin projects",
5
5
  "exports": {
6
6
  "./clerk": {
@@ -1,11 +1,13 @@
1
1
  'use client';
2
2
 
3
3
  import { useAuth } from '@clerk/nextjs';
4
- import { useEffect, useState } from 'react';
4
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
5
5
  import { CreditNavButton } from './credit-nav-button';
6
6
  import { CreditOverviewClient, type CreditOverviewTranslations } from './credit-overview-client';
7
7
  import type { CreditOverviewData } from './types';
8
8
 
9
+ export const DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT = 'windrun-huaiin:credit-overview:refresh';
10
+
9
11
  export interface CreditOverviewPayload {
10
12
  data: CreditOverviewData;
11
13
  totalLabel: string;
@@ -15,6 +17,19 @@ export interface CreditOverviewPayload {
15
17
  export interface CreditOverviewNavClientProps {
16
18
  locale: string;
17
19
  endpoint: string;
20
+ /**
21
+ * Browser event names that should trigger credit overview reload.
22
+ * Business apps can dispatch these events after credit balance changes.
23
+ *
24
+ * Default: ['windrun:credit-overview:refresh']
25
+ * Empty array means event listening is disabled.
26
+ */
27
+ refreshEvents?: string[];
28
+ /**
29
+ * Optional debounce for refresh event bursts.
30
+ * Default: 300ms.
31
+ */
32
+ refreshDebounceMs?: number;
18
33
  }
19
34
 
20
35
  function buildCreditOverviewUrl(endpoint: string, locale: string) {
@@ -23,12 +38,91 @@ function buildCreditOverviewUrl(endpoint: string, locale: string) {
23
38
  return url.toString();
24
39
  }
25
40
 
41
+ function normalizeRefreshEvents(refreshEvents: string[] | undefined) {
42
+ const events = refreshEvents ?? [DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT];
43
+ return Array.from(
44
+ new Set(
45
+ events
46
+ .map((eventName) => eventName.trim())
47
+ .filter((eventName) => eventName.length > 0),
48
+ ),
49
+ );
50
+ }
51
+
52
+ function buildRefreshEventsKey(refreshEvents: string[] | undefined) {
53
+ return normalizeRefreshEvents(refreshEvents).join('\n');
54
+ }
55
+
56
+ export function dispatchCreditOverviewRefresh(
57
+ eventName = DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT,
58
+ ) {
59
+ if (typeof window === 'undefined') {
60
+ return;
61
+ }
62
+
63
+ window.dispatchEvent(new CustomEvent(eventName));
64
+ }
65
+
26
66
  export function CreditOverviewNavClient({
27
67
  locale,
28
68
  endpoint,
69
+ refreshEvents,
70
+ refreshDebounceMs = 300,
29
71
  }: CreditOverviewNavClientProps) {
30
72
  const { isLoaded, isSignedIn, userId } = useAuth();
31
73
  const [payload, setPayload] = useState<CreditOverviewPayload | null>(null);
74
+ const abortControllerRef = useRef<AbortController | null>(null);
75
+ const isMountedRef = useRef(false);
76
+ const refreshEventsKey = buildRefreshEventsKey(refreshEvents);
77
+ const normalizedRefreshEvents = useMemo(
78
+ () => refreshEventsKey.split('\n').filter(Boolean),
79
+ [refreshEventsKey],
80
+ );
81
+
82
+ useEffect(() => {
83
+ isMountedRef.current = true;
84
+
85
+ return () => {
86
+ isMountedRef.current = false;
87
+ abortControllerRef.current?.abort();
88
+ };
89
+ }, []);
90
+
91
+ const loadCreditOverview = useCallback(async () => {
92
+ abortControllerRef.current?.abort();
93
+
94
+ const controller = new AbortController();
95
+ abortControllerRef.current = controller;
96
+
97
+ try {
98
+ const response = await fetch(buildCreditOverviewUrl(endpoint, locale), {
99
+ cache: 'no-store',
100
+ credentials: 'same-origin',
101
+ signal: controller.signal,
102
+ });
103
+
104
+ if (!response.ok) {
105
+ if (!controller.signal.aborted && isMountedRef.current) {
106
+ setPayload(null);
107
+ }
108
+ return;
109
+ }
110
+
111
+ const nextPayload = (await response.json()) as CreditOverviewPayload | null;
112
+ if (!controller.signal.aborted && isMountedRef.current) {
113
+ setPayload(nextPayload);
114
+ }
115
+ } catch (error) {
116
+ if (!controller.signal.aborted && isMountedRef.current) {
117
+ setPayload(null);
118
+ console.warn('[CreditOverviewNavClient] Failed to load credit overview', error);
119
+ }
120
+ } finally {
121
+ if (abortControllerRef.current === controller) {
122
+ abortControllerRef.current = null;
123
+ }
124
+ }
125
+ }, [endpoint, locale]);
32
126
 
33
127
  useEffect(() => {
34
128
  if (!isLoaded) {
@@ -36,44 +130,46 @@ export function CreditOverviewNavClient({
36
130
  }
37
131
 
38
132
  if (!isSignedIn) {
133
+ abortControllerRef.current?.abort();
134
+ abortControllerRef.current = null;
39
135
  setPayload(null);
40
136
  return;
41
137
  }
42
138
 
43
- const controller = new AbortController();
139
+ void loadCreditOverview();
140
+ }, [isLoaded, isSignedIn, loadCreditOverview, userId]);
44
141
 
45
- async function loadCreditOverview() {
46
- try {
47
- const response = await fetch(buildCreditOverviewUrl(endpoint, locale), {
48
- credentials: 'same-origin',
49
- signal: controller.signal,
50
- });
51
-
52
- if (!response.ok) {
53
- if (!controller.signal.aborted) {
54
- setPayload(null);
55
- }
56
- return;
57
- }
142
+ useEffect(() => {
143
+ if (!isLoaded || !isSignedIn || normalizedRefreshEvents.length === 0) {
144
+ return;
145
+ }
58
146
 
59
- const nextPayload = (await response.json()) as CreditOverviewPayload | null;
60
- if (!controller.signal.aborted) {
61
- setPayload(nextPayload);
62
- }
63
- } catch (error) {
64
- if (!controller.signal.aborted) {
65
- setPayload(null);
66
- console.warn('[CreditOverviewNavClient] Failed to load credit overview', error);
67
- }
147
+ let debounceTimer: number | null = null;
148
+
149
+ const refresh = () => {
150
+ if (debounceTimer) {
151
+ window.clearTimeout(debounceTimer);
68
152
  }
69
- }
70
153
 
71
- loadCreditOverview();
154
+ debounceTimer = window.setTimeout(() => {
155
+ void loadCreditOverview();
156
+ }, refreshDebounceMs);
157
+ };
158
+
159
+ for (const eventName of normalizedRefreshEvents) {
160
+ window.addEventListener(eventName, refresh);
161
+ }
72
162
 
73
163
  return () => {
74
- controller.abort();
164
+ if (debounceTimer) {
165
+ window.clearTimeout(debounceTimer);
166
+ }
167
+
168
+ for (const eventName of normalizedRefreshEvents) {
169
+ window.removeEventListener(eventName, refresh);
170
+ }
75
171
  };
76
- }, [endpoint, isLoaded, isSignedIn, locale, userId]);
172
+ }, [isLoaded, isSignedIn, loadCreditOverview, normalizedRefreshEvents, refreshDebounceMs]);
77
173
 
78
174
  if (!payload) {
79
175
  return null;
@@ -1,7 +1,11 @@
1
1
  'use client';
2
2
 
3
3
  export { CreditOverviewClient } from './credit-overview-client';
4
- export { CreditOverviewNavClient } from './credit-overview-nav-client';
4
+ export {
5
+ CreditOverviewNavClient,
6
+ DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT,
7
+ dispatchCreditOverviewRefresh,
8
+ } from './credit-overview-nav-client';
5
9
  export { CreditNavButton } from './credit-nav-button';
6
10
  export type { CreditOverviewTranslations } from './credit-overview-client';
7
11
  export type {