@orderly.network/ui-notification 2.8.2-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,847 @@
1
+ import { useMemo, useState, useEffect, useCallback } from 'react';
2
+ import { useTranslation } from '@orderly.network/i18n';
3
+ import { Flex, Text, cn, ChevronDownIcon, ScrollArea, Divider, Icon, ExtensionSlot, ExtensionPositionEnum, ChevronLeftIcon, ChevronRightIcon } from '@orderly.network/ui';
4
+ import { AnnouncementType, EMPTY_LIST } from '@orderly.network/types';
5
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
+ import { UTCDate, UTCDateMini } from '@date-fns/utc';
7
+ import { differenceInHours, format } from 'date-fns';
8
+ import { produce } from 'immer';
9
+ import { useOrderlyContext, useLocalStorage, useWS, useMaintenanceStatus, useQuery, MaintenanceStatus } from '@orderly.network/hooks';
10
+ import { useAppContext } from '@orderly.network/react-app';
11
+ import { getTimestamp } from '@orderly.network/utils';
12
+
13
+ // src/components/announcementCenter/announcementCenter.ui.tsx
14
+ var BattleIcon = (props) => {
15
+ return /* @__PURE__ */ jsxs(Icon, { size: 18, viewBox: "0 0 18 18", ...props, children: [
16
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
17
+ "linearGradient",
18
+ {
19
+ id: "paint0_linear_555_7374",
20
+ x1: "17.0157",
21
+ y1: "9.26513",
22
+ x2: "0.969849",
23
+ y2: "9.26513",
24
+ gradientUnits: "userSpaceOnUse",
25
+ children: [
26
+ /* @__PURE__ */ jsx("stop", { stopColor: "rgb(var(--oui-gradient-brand-end))" }),
27
+ /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "rgb(var(--oui-gradient-brand-start))" })
28
+ ]
29
+ }
30
+ ) }),
31
+ /* @__PURE__ */ jsx(
32
+ "path",
33
+ {
34
+ fill: "url(#paint0_linear_555_7374)",
35
+ fillOpacity: 1,
36
+ d: "m1.5 1.5.75 3 4.843 4.56-1.808 1.919-.63-.633-1.06 1.06.665.665-1.88 1.996-.35-.346-1.06 1.06 2.25 2.25 1.06-1.06-.348-.349 1.998-1.878.665.662 1.06-1.06-.63-.63L9 10.852l1.969 1.854-.639.639 1.06 1.06.672-.67 1.998 1.877-.358.358 1.064 1.06 2.25-2.25-1.06-1.06-.34.34-1.881-1.998.656-.657-1.06-1.06-.625.624-1.799-1.91.003-.003L9 7.03 4.5 2.25zm15 0-3 .75-3.636 3.861 2.022 2.025L15.75 4.5z"
37
+ }
38
+ )
39
+ ] });
40
+ };
41
+ var CampaignIcon = (props) => {
42
+ return /* @__PURE__ */ jsx(Icon, { size: 18, viewBox: "0 0 18 18", ...props, children: /* @__PURE__ */ jsx(
43
+ "path",
44
+ {
45
+ fill: "currentcolor",
46
+ fillOpacity: 1,
47
+ d: "m1.5 1.5.75 3 4.843 4.56-1.808 1.919-.63-.633-1.06 1.06.665.665-1.88 1.996-.35-.346-1.06 1.06 2.25 2.25 1.06-1.06-.348-.349 1.998-1.878.665.662 1.06-1.06-.63-.63L9 10.852l1.969 1.854-.639.639 1.06 1.06.672-.67 1.998 1.877-.358.358 1.064 1.06 2.25-2.25-1.06-1.06-.34.34-1.881-1.998.656-.657-1.06-1.06-.625.624-1.799-1.91.003-.003L9 7.03 4.5 2.25zm15 0-3 .75-3.636 3.861 2.022 2.025L15.75 4.5z"
48
+ }
49
+ ) });
50
+ };
51
+ var ArrowRightShortIcon = (props) => {
52
+ return /* @__PURE__ */ jsxs(Icon, { size: 18, viewBox: "0 0 18 18", ...props, children: [
53
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
54
+ "linearGradient",
55
+ {
56
+ id: "paint0_linear_555_7374",
57
+ x1: "17.0157",
58
+ y1: "9.26513",
59
+ x2: "0.969849",
60
+ y2: "9.26513",
61
+ gradientUnits: "userSpaceOnUse",
62
+ children: [
63
+ /* @__PURE__ */ jsx("stop", { stopColor: "rgb(var(--oui-gradient-brand-end))" }),
64
+ /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "rgb(var(--oui-gradient-brand-start))" })
65
+ ]
66
+ }
67
+ ) }),
68
+ /* @__PURE__ */ jsx(
69
+ "path",
70
+ {
71
+ fill: "url(#paint0_linear_555_7374)",
72
+ fillOpacity: 1,
73
+ d: "M4.509 8.995a.75.75 0 0 1 .75-.75h5.666L8.7 5.998l1.054-1.054 3.535 3.512c.147.146.22.343.22.54a.76.76 0 0 1-.22.537l-3.535 3.512L8.7 11.992l2.225-2.248H5.258a.75.75 0 0 1-.749-.75"
74
+ }
75
+ )
76
+ ] });
77
+ };
78
+ var FundIcon = (props) => {
79
+ return /* @__PURE__ */ jsx(Icon, { size: 18, viewBox: "0 0 18 18", ...props, children: /* @__PURE__ */ jsx(
80
+ "path",
81
+ {
82
+ fill: "currentcolor",
83
+ fillOpacity: 0.8,
84
+ d: "M15.694 7.087c-.788-.393-1.857-.618-2.925-.618-1.125 0-2.138.225-2.925.618-.056 0-.113.057-.113.057V3.769c0-.9-.731-1.575-1.462-1.913-.788-.394-1.857-.619-2.925-.619-1.069 0-2.25.225-3.038.62C1.575 2.193.844 2.868.844 3.768v10.519c0 .9.731 1.575 1.462 1.912.788.394 1.856.619 2.925.619s2.138-.225 2.925-.619c.281-.169.563-.337.788-.562.225.225.506.393.787.562.788.394 1.857.619 2.925.619 1.125 0 2.138-.225 2.925-.619.732-.394 1.463-1.012 1.463-1.912V9c.112-.9-.619-1.519-1.35-1.913m-7.369 7.144c0 .113-.112.45-.731.732-.563.28-1.407.506-2.363.506s-1.8-.169-2.362-.506c-.619-.282-.731-.62-.731-.732V13.5c.056 0 .112 0 .168.056.788.394 1.856.619 2.925.619s2.138-.225 2.925-.619c.056 0 .113-.056.113-.056v.731zm0-2.587c0 .112-.112.45-.731.731-.563.281-1.407.506-2.363.506s-1.8-.168-2.362-.506c-.619-.281-.731-.619-.731-.731v-.788c.056 0 .112.056.112.056.788.394 1.856.62 2.925.62s2.138-.226 2.925-.62c.056 0 .113-.056.113-.056v.788zm0-2.644c0 .112-.112.45-.731.731-.563.281-1.407.507-2.363.507s-1.8-.17-2.362-.507C2.25 9.45 2.138 9.112 2.138 9v-.788c.056 0 .112.057.112.057.788.393 1.856.618 2.925.618S7.313 8.662 8.1 8.27c.056 0 .113-.057.113-.057V9zm0-2.644c0 .113-.112.45-.731.731-.563.282-1.407.507-2.363.507s-1.8-.169-2.362-.507c-.619-.28-.731-.618-.731-.73v-.732c.056 0 .112 0 .168.056.788.394 1.856.619 2.925.619s2.138-.225 2.925-.619c.056 0 .113-.056.113-.056v.731zM7.594 4.5c-.563.281-1.407.506-2.363.506S3.488 4.781 2.925 4.5c-.619-.338-.731-.619-.731-.731 0-.113.112-.45.731-.732.563-.28 1.406-.506 2.363-.506.956 0 1.8.169 2.362.506.619.282.731.62.731.732-.056.112-.168.393-.787.731m8.212 9.731c0 .113-.112.45-.731.732-.562.28-1.406.506-2.362.506s-1.8-.169-2.363-.506c-.619-.282-.731-.62-.731-.732V13.5c.056 0 .112.056.112.056.788.394 1.857.619 2.925.619 1.125 0 2.138-.225 2.925-.619.056 0 .113-.056.113-.056v.731zm0-2.587c0 .112-.112.45-.731.731-.562.281-1.406.506-2.362.506s-1.8-.168-2.363-.506c-.619-.281-.731-.619-.731-.731v-.788c.056 0 .112.056.112.056.788.394 1.857.62 2.925.62 1.125 0 2.138-.226 2.925-.62.056 0 .113-.056.113-.056v.788zm-.675-1.913c-.562.281-1.406.507-2.362.507s-1.8-.17-2.363-.507c-.619-.281-.731-.619-.731-.731 0-.113.112-.45.731-.731.563-.282 1.406-.507 2.363-.507.956 0 1.8.17 2.362.507.619.281.732.618.732.731-.057.112-.17.45-.732.731"
85
+ }
86
+ ) });
87
+ };
88
+ var AnnouncementIcon = (props) => {
89
+ return /* @__PURE__ */ jsx(Icon, { size: 18, viewBox: "0 0 18 18", ...props, children: /* @__PURE__ */ jsx(
90
+ "path",
91
+ {
92
+ fill: "currentcolor",
93
+ fillOpacity: 0.8,
94
+ d: "M11.53 2.255a.745.745 0 0 0-.82.165c-.525.524-1.188.959-1.947 1.284-.77.33-2.353.757-3.508.75-2.248-.015-3.756 1.259-3.756 3.726 0 2.163 1.228 3.42 2.994 3.703l.006 1.565a2.25 2.25 0 0 0 2.25 2.247c1.142 0 2.083-.883 2.228-1.988.007-.053.022-.26.022-1.01.674.315 1.232.812 1.711 1.29.473.472 1.29.13 1.29-.538 0-.678-.004-1.906-.004-3.13.884-.327 1.503-1.165 1.503-2.115s-.585-1.81-1.496-2.129c0-1.225-.004-2.439-.004-3.117a.76.76 0 0 0-.469-.703m1.805 1.335a.73.73 0 0 0-.445.351.75.75 0 0 0 .258 1.03 3.74 3.74 0 0 1 1.851 3.233 3.74 3.74 0 0 1-1.851 3.231.76.76 0 0 0-.282 1.03.754.754 0 0 0 1.032.258 5.24 5.24 0 0 0 2.601-4.52 5.24 5.24 0 0 0-2.601-4.519.74.74 0 0 0-.563-.094m-2.832.884c0 .694-.004 1.417-.004 2.231v2.997c0 .815.003 1.508.003 2.202-1.52-.896-3.085-1.294-4.501-1.421 0-1.144-.004-3.406-.004-4.584.147-.007.318-.026.565-.06a11.2 11.2 0 0 0 2.812-.773c.43-.184.75-.35 1.129-.592m-6.005 1.55-.001 4.34c-.976-.27-1.498-.959-1.498-2.184 0-1.21.47-1.928 1.499-2.155M6 11.998c.238.008 1.098.161 1.493.261l.007 1.19a.75.75 0 0 1-1.5 0z"
95
+ }
96
+ ) });
97
+ };
98
+ var SecurityIcon = (props) => {
99
+ return /* @__PURE__ */ jsxs(Icon, { size: 18, viewBox: "0 0 18 18", ...props, children: [
100
+ /* @__PURE__ */ jsx(
101
+ "path",
102
+ {
103
+ d: "M6.563 7.678V6.603c0-1.153 1.09-2.088 2.437-2.088s2.438.935 2.438 2.088v1.075c.448 0 .812.311.812.696v3.479c0 .384-.364.696-.812.696H6.563c-.449 0-.813-.312-.813-.696v-3.48c0-.384.364-.695.813-.695m1.187-.006 1.431.006h1.07V6.564c0-.64-.504-1.104-1.25-1.104-.748 0-1.25.465-1.25 1.104zm1.956 2.14c0-.335-.317-.605-.706-.605-.39 0-.706.27-.706.604v.77c0 .335.316.605.706.605s.706-.27.706-.604z",
104
+ fill: "currentcolor",
105
+ fillOpacity: ".8"
106
+ }
107
+ ),
108
+ /* @__PURE__ */ jsx(
109
+ "path",
110
+ {
111
+ d: "M2 3.607c.003 5.606.146 11.651 6.879 13.378.078.02.164.02.242 0C15.854 15.258 15.997 9.213 16 3.607c0-.217-.14-.41-.345-.477L9.31 1.05a1 1 0 0 0-.62 0L2.345 3.13A.5.5 0 0 0 2 3.607m2.326 7.63c-.707-1.954-.81-4.33-.824-6.902L9 2.532l5.498 1.803c-.014 2.573-.117 4.948-.824 6.901-.697 1.93-1.987 3.463-4.674 4.222-2.687-.759-3.977-2.293-4.674-4.222",
112
+ fill: "currentcolor",
113
+ fillOpacity: ".8"
114
+ }
115
+ )
116
+ ] });
117
+ };
118
+ var AnnouncementItem = (props) => {
119
+ const { t } = useTranslation();
120
+ const Icon2 = useMemo(() => {
121
+ switch (props.type) {
122
+ case AnnouncementType.Campaign:
123
+ return CampaignIcon;
124
+ case AnnouncementType.Listing:
125
+ return FundIcon;
126
+ case AnnouncementType.Maintenance:
127
+ return SecurityIcon;
128
+ case AnnouncementType.Delisting:
129
+ default:
130
+ return AnnouncementIcon;
131
+ }
132
+ }, [props.type]);
133
+ const title = useMemo(() => {
134
+ switch (props.type) {
135
+ case AnnouncementType.Campaign:
136
+ return t("notification.campaign");
137
+ case AnnouncementType.Delisting:
138
+ return t("notification.delisting");
139
+ case AnnouncementType.Listing:
140
+ return t("notification.listing");
141
+ case AnnouncementType.Maintenance:
142
+ return t("notification.maintenance");
143
+ default:
144
+ return t("notification.general");
145
+ }
146
+ }, [props.type, t]);
147
+ const action = useMemo(() => {
148
+ if (props.type === AnnouncementType.Campaign && typeof props.url === "string" && props.url !== "" && typeof props.onItemClick === "function") {
149
+ return /* @__PURE__ */ jsxs(
150
+ Flex,
151
+ {
152
+ gap: 1,
153
+ itemAlign: "center",
154
+ className: "oui-cursor-pointer",
155
+ onClick: (event) => {
156
+ event.stopPropagation();
157
+ props.onItemClick(props.url);
158
+ },
159
+ children: [
160
+ /* @__PURE__ */ jsx(
161
+ Text,
162
+ {
163
+ size: "xs",
164
+ color: "buy",
165
+ className: "oui-bg-clip-text oui-text-transparent oui-gradient-brand",
166
+ children: t("notification.joinNow")
167
+ }
168
+ ),
169
+ /* @__PURE__ */ jsx(ArrowRightShortIcon, { size: 18 })
170
+ ]
171
+ }
172
+ );
173
+ }
174
+ return null;
175
+ }, [props.type, props.url, t]);
176
+ const updateTime = useMemo(() => {
177
+ if (props.type === AnnouncementType.Maintenance) {
178
+ return /* @__PURE__ */ jsx(Text, { size: "2xs", intensity: 36, children: t("notification.recentlyUpdated") });
179
+ }
180
+ return /* @__PURE__ */ jsx(
181
+ Text.formatted,
182
+ {
183
+ size: "2xs",
184
+ intensity: 36,
185
+ rule: "date",
186
+ formatString: "yyyy-MM-dd HH:mm:ss",
187
+ children: props.updatedTime
188
+ }
189
+ );
190
+ }, [props.updatedTime, props.type, t]);
191
+ return /* @__PURE__ */ jsxs(
192
+ Flex,
193
+ {
194
+ gap: 2,
195
+ itemAlign: "start",
196
+ className: cn(
197
+ "oui-px-2 oui-py-[6px] oui-text-base-contrast-80",
198
+ !props.showDivider && "oui-rounded-md hover:oui-bg-base-6",
199
+ !props.showDivider && props.expanded && "oui-bg-base-6",
200
+ props.className
201
+ ),
202
+ onClick: () => {
203
+ props.onExpandToggle?.();
204
+ },
205
+ children: [
206
+ /* @__PURE__ */ jsx(Icon2, { color: "white", className: "oui-mt-3 oui-shrink-0" }),
207
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", itemAlign: "start", grow: true, children: [
208
+ /* @__PURE__ */ jsx(Text, { size: "xs", intensity: 80, weight: "bold", children: title }),
209
+ updateTime,
210
+ /* @__PURE__ */ jsx(
211
+ "div",
212
+ {
213
+ className: "oui-grid oui-transition-all oui-duration-300 oui-ease-in-out",
214
+ style: {
215
+ gridTemplateRows: props.expanded ? "1fr" : "0fr"
216
+ },
217
+ children: /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-flex-col oui-gap-2 oui-overflow-hidden", children: [
218
+ /* @__PURE__ */ jsx(Text, { size: "2xs", intensity: 80, as: "div", className: "oui-pt-2", children: props.message }),
219
+ action
220
+ ] })
221
+ }
222
+ )
223
+ ] }),
224
+ /* @__PURE__ */ jsx("div", { className: "oui-pt-3", children: /* @__PURE__ */ jsx(
225
+ ChevronDownIcon,
226
+ {
227
+ color: "white",
228
+ size: 18,
229
+ className: `oui-transition-transform oui-duration-300 oui-ease-in-out ${props.expanded ? "oui-rotate-180" : "oui-rotate-0"}`
230
+ }
231
+ ) })
232
+ ]
233
+ }
234
+ );
235
+ };
236
+ var AnnouncementContent = (props) => {
237
+ const { dataSource, current, onExpandToggle, onItemClick } = props;
238
+ const { t } = useTranslation();
239
+ if (!Array.isArray(dataSource) || dataSource.length === 0) {
240
+ return /* @__PURE__ */ jsx("div", { className: "oui-flex oui-h-[160px] oui-items-center oui-justify-center", children: /* @__PURE__ */ jsx(
241
+ ExtensionSlot,
242
+ {
243
+ position: ExtensionPositionEnum.EmptyDataIdentifier,
244
+ title: t("notification.empty")
245
+ }
246
+ ) });
247
+ }
248
+ return /* @__PURE__ */ jsx(
249
+ "div",
250
+ {
251
+ className: cn(
252
+ "p-5 oui-flex oui-flex-col oui-space-y-1",
253
+ props.showDivider && "[&>*:not(:first-child)]:oui-border-t [&>*:not(:first-child)]:oui-border-line-12 [&>*:not(:first-child)]:oui-pt-1"
254
+ ),
255
+ children: dataSource.map((item) => /* @__PURE__ */ jsx(
256
+ AnnouncementItem,
257
+ {
258
+ url: item.url,
259
+ onItemClick,
260
+ message: item.message,
261
+ updatedTime: item.updated_time ?? 0,
262
+ expanded: current === item.announcement_id,
263
+ type: item.type,
264
+ showDivider: props.showDivider,
265
+ onExpandToggle: () => {
266
+ if (current === item.announcement_id) {
267
+ onExpandToggle(null);
268
+ } else {
269
+ onExpandToggle(item.announcement_id);
270
+ }
271
+ }
272
+ },
273
+ item.announcement_id
274
+ ))
275
+ }
276
+ );
277
+ };
278
+ var AnnouncementCenterUI = (props) => {
279
+ const { t } = useTranslation();
280
+ const [expanded, setExpanded] = useState(null);
281
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
282
+ /* @__PURE__ */ jsx("div", { className: "oui-px-5 oui-pt-4", children: /* @__PURE__ */ jsx(Text, { intensity: 80, weight: "bold", children: t("notification.title") }) }),
283
+ /* @__PURE__ */ jsx(ScrollArea, { className: "oui-flex oui-h-[300px] oui-flex-col oui-space-y-1 oui-p-3", children: /* @__PURE__ */ jsx(
284
+ AnnouncementContent,
285
+ {
286
+ dataSource: props.dataSource,
287
+ current: expanded,
288
+ onExpandToggle: setExpanded,
289
+ onItemClick: props.onItemClick
290
+ }
291
+ ) })
292
+ ] });
293
+ };
294
+ var CampaignContentCard = ({ message, coverImage, url, onItemClick }) => {
295
+ const { t } = useTranslation();
296
+ return /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-flex-col oui-gap-5", children: [
297
+ /* @__PURE__ */ jsx(Text, { size: "sm", weight: "bold", children: message }),
298
+ /* @__PURE__ */ jsx(
299
+ "div",
300
+ {
301
+ className: "oui-rounded-xl oui-bg-base-9 oui-bg-cover oui-bg-center oui-bg-no-repeat",
302
+ style: {
303
+ backgroundImage: `url(${coverImage})`,
304
+ height: "100px"
305
+ }
306
+ }
307
+ ),
308
+ typeof url === "string" && url !== "" && typeof onItemClick === "function" && /* @__PURE__ */ jsxs(
309
+ "button",
310
+ {
311
+ className: "oui-flex oui-items-center oui-gap-1",
312
+ onClick: () => onItemClick(url),
313
+ children: [
314
+ /* @__PURE__ */ jsx(
315
+ Text,
316
+ {
317
+ size: "xs",
318
+ color: "buy",
319
+ className: "oui-bg-clip-text oui-text-transparent oui-gradient-brand",
320
+ children: t("notification.joinNow")
321
+ }
322
+ ),
323
+ /* @__PURE__ */ jsx(ArrowRightShortIcon, { size: 18, color: "success" })
324
+ ]
325
+ }
326
+ )
327
+ ] });
328
+ };
329
+ var MaintenanceContentCard = ({ message, startTime, endTime }) => {
330
+ const { t } = useTranslation();
331
+ const formattedMessage = useMemo(() => {
332
+ const hours = differenceInHours(endTime, startTime);
333
+ const startUtc = new UTCDate(startTime);
334
+ const endUtc = new UTCDate(endTime);
335
+ const startTimeFormatted = format(startUtc, "HH:mm");
336
+ const endTimeFormatted = format(endUtc, "hh:mm a");
337
+ return t("notification.maintenanceDuration", {
338
+ hours,
339
+ startTimeFormatted,
340
+ endTimeFormatted
341
+ });
342
+ }, [startTime, endTime, t]);
343
+ return /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-flex-col oui-gap-1", children: [
344
+ /* @__PURE__ */ jsx(Text, { size: "xs", intensity: 54, children: t("notification.recentlyUpdated") }),
345
+ /* @__PURE__ */ jsx(Flex, { itemAlign: "center", children: /* @__PURE__ */ jsx(Text, { size: "xs", weight: "bold", children: formattedMessage }) }),
346
+ message && /* @__PURE__ */ jsx(Text, { size: "2xs", intensity: 80, as: "div", className: "oui-mt-2", children: message })
347
+ ] });
348
+ };
349
+ var DelistingContentCard = ({ message, updateTime }) => {
350
+ return /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-flex-col oui-gap-1", children: [
351
+ /* @__PURE__ */ jsx(
352
+ Text.formatted,
353
+ {
354
+ rule: "date",
355
+ intensity: 54,
356
+ formatString: "yyyy-MM-dd HH:mm:ss",
357
+ size: "xs",
358
+ children: updateTime
359
+ }
360
+ ),
361
+ /* @__PURE__ */ jsx(Text, { size: "sm", weight: "bold", children: message })
362
+ ] });
363
+ };
364
+ var ListingContentCard = ({ message, updateTime }) => {
365
+ return /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-flex-col oui-gap-1", children: [
366
+ /* @__PURE__ */ jsx(
367
+ Text.formatted,
368
+ {
369
+ rule: "date",
370
+ intensity: 54,
371
+ formatString: "yyyy-MM-dd HH:mm:ss",
372
+ size: "xs",
373
+ children: updateTime
374
+ }
375
+ ),
376
+ /* @__PURE__ */ jsx(Text, { size: "sm", weight: "bold", children: message })
377
+ ] });
378
+ };
379
+ var NotificationHeader = (props) => {
380
+ const { t } = useTranslation();
381
+ const { expanded } = props;
382
+ const { type } = props.dataSource[props.current];
383
+ const title = useMemo(() => {
384
+ switch (type) {
385
+ case AnnouncementType.Campaign:
386
+ return /* @__PURE__ */ jsx(
387
+ Text,
388
+ {
389
+ size: "sm",
390
+ className: "oui-text-transparent oui-bg-clip-text oui-gradient-brand",
391
+ children: t("notification.campaignTitle")
392
+ }
393
+ );
394
+ case AnnouncementType.Delisting:
395
+ return /* @__PURE__ */ jsx(Text, { size: "sm", children: t("notification.delistingTitle") });
396
+ case AnnouncementType.Listing:
397
+ return /* @__PURE__ */ jsx(Text, { size: "sm", color: "buy", children: t("notification.listing") });
398
+ case AnnouncementType.Maintenance:
399
+ return /* @__PURE__ */ jsx(Text, { size: "sm", color: "warning", children: t("notification.maintenanceTitle") });
400
+ default:
401
+ return /* @__PURE__ */ jsx(Text, { size: "sm", color: "inherit", children: t("notification.generalTitle") });
402
+ }
403
+ }, [type, t]);
404
+ const icon = useMemo(() => {
405
+ switch (type) {
406
+ case AnnouncementType.Campaign:
407
+ return /* @__PURE__ */ jsx(BattleIcon, { color: "white" });
408
+ case AnnouncementType.Listing:
409
+ return /* @__PURE__ */ jsx(FundIcon, { color: "success" });
410
+ case AnnouncementType.Maintenance:
411
+ return /* @__PURE__ */ jsx(SecurityIcon, { color: "warning" });
412
+ case AnnouncementType.Delisting:
413
+ default:
414
+ return /* @__PURE__ */ jsx(AnnouncementIcon, { color: "white" });
415
+ }
416
+ }, [type]);
417
+ return /* @__PURE__ */ jsxs(Flex, { itemAlign: "center", justify: "between", className: "oui-px-4 oui-py-3", children: [
418
+ /* @__PURE__ */ jsxs("div", { className: "orderly-notification-header oui-flex oui-items-center oui-gap-2", children: [
419
+ icon,
420
+ title
421
+ ] }),
422
+ /* @__PURE__ */ jsx(
423
+ "button",
424
+ {
425
+ onClick: props.onExpandToggle,
426
+ className: "oui-transition-transform oui-duration-300",
427
+ style: {
428
+ transform: !expanded ? "rotate(180deg)" : "rotate(0deg)"
429
+ },
430
+ children: /* @__PURE__ */ jsx(ChevronDownIcon, { size: 18, color: "white" })
431
+ }
432
+ )
433
+ ] });
434
+ };
435
+ var NotificationFooter = (props) => {
436
+ const { total, current, onCloseAll, onPrev, onNext } = props;
437
+ const { t } = useTranslation();
438
+ return /* @__PURE__ */ jsxs(
439
+ Flex,
440
+ {
441
+ className: "orderly-notification-footer oui-px-4 oui-py-2",
442
+ itemAlign: "center",
443
+ justify: "between",
444
+ children: [
445
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
446
+ /* @__PURE__ */ jsx(
447
+ "button",
448
+ {
449
+ disabled: current - 1 < 0,
450
+ onClick: onPrev,
451
+ className: "oui-flex oui-size-[18px] oui-items-center oui-justify-center oui-rounded-full oui-bg-base-6 hover:oui-bg-base-5 disabled:oui-opacity-50",
452
+ children: /* @__PURE__ */ jsx(ChevronLeftIcon, { size: 14, color: "white" })
453
+ }
454
+ ),
455
+ /* @__PURE__ */ jsxs(Text, { intensity: 54, size: "sm", children: [
456
+ current + 1,
457
+ "/",
458
+ total
459
+ ] }),
460
+ /* @__PURE__ */ jsx(
461
+ "button",
462
+ {
463
+ disabled: current + 1 >= total,
464
+ onClick: onNext,
465
+ className: "oui-flex oui-size-[18px] oui-items-center oui-justify-center oui-rounded-full oui-bg-base-6 hover:oui-bg-base-5 disabled:oui-opacity-50",
466
+ children: /* @__PURE__ */ jsx(ChevronRightIcon, { size: 14, color: "white" })
467
+ }
468
+ )
469
+ ] }),
470
+ /* @__PURE__ */ jsx("button", { onClick: onCloseAll, children: /* @__PURE__ */ jsx(Text, { size: "xs", color: "primary", children: t("notification.closeAll", { total }) }) })
471
+ ]
472
+ }
473
+ );
474
+ };
475
+ var NotificationContent = (props) => {
476
+ const elements = useMemo(() => {
477
+ return props.dataSource.map((message) => {
478
+ const { type } = message;
479
+ switch (type) {
480
+ case AnnouncementType.Campaign:
481
+ return /* @__PURE__ */ jsx(
482
+ CampaignContentCard,
483
+ {
484
+ message: message.message,
485
+ coverImage: message.coverImage ?? "",
486
+ updateTime: message.updated_time ?? 0,
487
+ url: message.url ?? "",
488
+ onItemClick: props.onItemClick
489
+ }
490
+ );
491
+ case AnnouncementType.Maintenance:
492
+ return /* @__PURE__ */ jsx(
493
+ MaintenanceContentCard,
494
+ {
495
+ message: message.message,
496
+ startTime: message.startTime ?? 0,
497
+ endTime: message.endTime ?? 0
498
+ }
499
+ );
500
+ case AnnouncementType.Delisting:
501
+ return /* @__PURE__ */ jsx(
502
+ DelistingContentCard,
503
+ {
504
+ message: message.message,
505
+ updateTime: message.updated_time ?? 0
506
+ }
507
+ );
508
+ default:
509
+ return /* @__PURE__ */ jsx(
510
+ ListingContentCard,
511
+ {
512
+ message: message.message,
513
+ updateTime: message.updated_time ?? 0
514
+ }
515
+ );
516
+ }
517
+ });
518
+ }, [props.dataSource]);
519
+ return /* @__PURE__ */ jsx(Fragment, { children: elements[props.current] });
520
+ };
521
+ var NotificationUI = (props) => {
522
+ const [expanded, setExpanded] = useState(true);
523
+ const [current, setCurrent] = useState(0);
524
+ const len = useMemo(() => props.dataSource?.length ?? 0, [props.dataSource]);
525
+ if (len === 0) {
526
+ return null;
527
+ }
528
+ return /* @__PURE__ */ jsxs("div", { className: "orderly-notification oui-w-full ", children: [
529
+ /* @__PURE__ */ jsx(
530
+ NotificationHeader,
531
+ {
532
+ dataSource: props.dataSource ?? [],
533
+ current,
534
+ expanded,
535
+ onExpandToggle: () => {
536
+ setExpanded(!expanded);
537
+ }
538
+ }
539
+ ),
540
+ /* @__PURE__ */ jsx(Divider, { className: "oui-mx-4" }),
541
+ /* @__PURE__ */ jsx(
542
+ "div",
543
+ {
544
+ className: "oui-grid oui-transition-all oui-duration-300 oui-ease-in-out",
545
+ style: {
546
+ gridTemplateRows: expanded ? "1fr" : "0fr"
547
+ },
548
+ children: /* @__PURE__ */ jsx("div", { className: "oui-min-h-0 oui-overflow-hidden ", children: /* @__PURE__ */ jsx("div", { className: "oui-px-4 oui-py-3", children: /* @__PURE__ */ jsx(
549
+ NotificationContent,
550
+ {
551
+ dataSource: props.dataSource ?? [],
552
+ current,
553
+ onItemClick: props.onItemClick
554
+ }
555
+ ) }) })
556
+ }
557
+ ),
558
+ /* @__PURE__ */ jsx(
559
+ NotificationFooter,
560
+ {
561
+ total: len,
562
+ current,
563
+ onCloseAll: props.onClose ?? (() => {
564
+ }),
565
+ onPrev: () => {
566
+ if (current - 1 < 0) {
567
+ return;
568
+ }
569
+ setCurrent(current - 1);
570
+ },
571
+ onNext: () => {
572
+ if (current + 1 >= len) {
573
+ return;
574
+ }
575
+ setCurrent(current + 1);
576
+ }
577
+ }
578
+ )
579
+ ] });
580
+ };
581
+ var oneDay = 1e3 * 60 * 60 * 24;
582
+ var maintentanceId = "-1";
583
+ var ORDERLY_ANNOUNCEMENT_KEY = "orderly_announcement";
584
+ var getTimeString = (timestamp) => {
585
+ const date = format(new UTCDateMini(timestamp), "MMM dd");
586
+ const time = format(new UTCDateMini(timestamp), "h:mm aa");
587
+ return `${time} (UTC) on ${date}`;
588
+ };
589
+ var sortDataByUpdatedTime = (ori) => {
590
+ return produce(ori, (draft) => {
591
+ if (Array.isArray(draft.rows)) {
592
+ draft.rows.sort((a, b) => {
593
+ if (a.updated_time && b.updated_time) {
594
+ return b.updated_time - a.updated_time;
595
+ }
596
+ return 0;
597
+ });
598
+ }
599
+ });
600
+ };
601
+ var useAnnouncementData = () => {
602
+ const ws = useWS();
603
+ const [announcementStore, setStore] = useLocalStorage(
604
+ ORDERLY_ANNOUNCEMENT_KEY,
605
+ {}
606
+ );
607
+ const [tips, setTips] = useState({});
608
+ const [maintenanceDialogInfo, setMaintenanceDialogInfo] = useState();
609
+ const { startTime, endTime, status, brokerName } = useMaintenanceStatus();
610
+ const { t } = useTranslation();
611
+ const { data: announcements } = useQuery(
612
+ `/v2/public/announcement`,
613
+ {
614
+ revalidateOnFocus: false,
615
+ refreshInterval: 60 * 60 * 1e3,
616
+ // refresh every 1 hour
617
+ formatter: (data) => data
618
+ }
619
+ );
620
+ const getMaintentTipsContent = (brokerName2, startDate, endDate) => t("maintenance.tips.description", { brokerName: brokerName2, startDate, endDate });
621
+ const getMaintentDialogContent = (brokerName2, endDate) => t("maintenance.dialog.description", { brokerName: brokerName2, endDate });
622
+ useEffect(() => {
623
+ const unsubscribe = ws.subscribe("announcement", {
624
+ onMessage(message) {
625
+ if (message) {
626
+ setTips((prev) => {
627
+ return produce(prev, (draft) => {
628
+ if (!Array.isArray(draft.rows)) {
629
+ draft.rows = [];
630
+ }
631
+ const idx = draft.rows.findIndex(
632
+ (tip) => tip.announcement_id === message.announcement_id
633
+ );
634
+ if (idx !== -1) {
635
+ draft.rows.splice(idx, 1);
636
+ }
637
+ draft.rows.push({
638
+ announcement_id: message.announcement_id,
639
+ message: message.message,
640
+ url: message.url,
641
+ i18n: message.i18n,
642
+ type: message.type,
643
+ updated_time: message.updated_time
644
+ });
645
+ });
646
+ });
647
+ setStore((prev) => ({ ...prev, show: true }));
648
+ }
649
+ },
650
+ onError(err) {
651
+ }
652
+ });
653
+ return () => {
654
+ unsubscribe?.();
655
+ };
656
+ }, [ws]);
657
+ useEffect(() => {
658
+ if (!announcements?.rows) {
659
+ return;
660
+ }
661
+ const apiTime = announcements.last_updated_time ?? 0;
662
+ const cachedTime = announcementStore.lastUpdateTime ?? 0;
663
+ if (cachedTime < apiTime) {
664
+ setTips((prev) => ({ ...prev, rows: announcements?.rows }));
665
+ setStore({ show: true, lastUpdateTime: apiTime });
666
+ } else {
667
+ setTips((prev) => {
668
+ return produce(prev, (draft) => {
669
+ if (announcements?.rows?.length) {
670
+ const existingIds = new Set(
671
+ prev.rows?.map((tip) => tip.announcement_id)
672
+ );
673
+ const maintenanceTip = prev.rows?.find(
674
+ (tip) => tip.announcement_id === maintentanceId
675
+ );
676
+ draft.rows = [];
677
+ announcements.rows.forEach((item) => {
678
+ if (!existingIds.has(item.announcement_id)) {
679
+ draft.rows?.push(item);
680
+ }
681
+ });
682
+ if (maintenanceTip) {
683
+ draft.rows.unshift(maintenanceTip);
684
+ }
685
+ } else {
686
+ const idx = draft.rows?.findIndex(
687
+ (tip) => tip.announcement_id === maintentanceId
688
+ );
689
+ if (idx !== void 0 && idx !== -1) {
690
+ draft.rows?.splice(idx, 1);
691
+ }
692
+ }
693
+ });
694
+ });
695
+ }
696
+ }, [announcements]);
697
+ useEffect(() => {
698
+ const startDate = startTime ? getTimeString(startTime) : "-";
699
+ const endDate = endTime ? getTimeString(endTime) : "-";
700
+ if (status === MaintenanceStatus.Maintenance) {
701
+ setMaintenanceDialogInfo(getMaintentDialogContent(brokerName, endDate));
702
+ return;
703
+ }
704
+ setMaintenanceDialogInfo(void 0);
705
+ if (startTime) {
706
+ if (startTime < getTimestamp() + oneDay) {
707
+ setTips(
708
+ (prev) => produce(prev, (draft) => {
709
+ if (!Array.isArray(draft.rows)) {
710
+ draft.rows = [];
711
+ }
712
+ draft.rows = [
713
+ {
714
+ announcement_id: maintentanceId,
715
+ type: AnnouncementType.Maintenance,
716
+ /** @ts-ignore */
717
+ startTime,
718
+ /** @ts-ignore */
719
+ endTime,
720
+ message: getMaintentTipsContent(brokerName, startDate, endDate)
721
+ },
722
+ ...draft.rows.filter(
723
+ (tip) => tip.type !== AnnouncementType.Maintenance
724
+ )
725
+ ];
726
+ })
727
+ );
728
+ }
729
+ } else {
730
+ setTips((prev) => {
731
+ return produce(prev, (draft) => {
732
+ const index = draft.rows?.findIndex(
733
+ (tip) => tip.announcement_id === maintentanceId
734
+ );
735
+ if (index !== void 0 && index !== -1) {
736
+ draft.rows?.splice(index, 1);
737
+ }
738
+ });
739
+ });
740
+ }
741
+ }, [startTime, endTime, status, brokerName, t]);
742
+ return {
743
+ tips: sortDataByUpdatedTime(tips),
744
+ maintenanceDialogInfo
745
+ };
746
+ };
747
+ var useAnnouncement = (options) => {
748
+ const { showAnnouncement, setShowAnnouncement } = useAppContext();
749
+ const { dataAdapter } = useOrderlyContext();
750
+ const { tips, maintenanceDialogInfo } = useAnnouncementData();
751
+ const memoizedTips = useMemo(() => {
752
+ if (typeof dataAdapter?.announcementList === "function") {
753
+ return dataAdapter.announcementList(
754
+ tips?.rows ?? EMPTY_LIST
755
+ );
756
+ }
757
+ return tips?.rows ?? EMPTY_LIST;
758
+ }, [dataAdapter?.announcementList, tips?.rows]);
759
+ const [announcementStore, setStore] = useLocalStorage(
760
+ ORDERLY_ANNOUNCEMENT_KEY,
761
+ {}
762
+ );
763
+ const closeTips = () => {
764
+ setStore((prev) => ({ ...prev, show: false }));
765
+ };
766
+ useEffect(() => {
767
+ const len = memoizedTips.length;
768
+ setShowAnnouncement(
769
+ Boolean(len) && announcementStore.show && !options?.hideTips
770
+ );
771
+ }, [
772
+ memoizedTips,
773
+ announcementStore.show,
774
+ options?.hideTips,
775
+ setShowAnnouncement
776
+ ]);
777
+ return {
778
+ maintenanceDialogInfo,
779
+ tips: memoizedTips,
780
+ closeTips,
781
+ showAnnouncement
782
+ };
783
+ };
784
+
785
+ // src/pages/announcementCenter.script.tsx
786
+ var useAnnouncementCenterScript = () => {
787
+ const { tips } = useAnnouncement();
788
+ const [current, setCurrent] = useState(null);
789
+ return {
790
+ dataSource: tips,
791
+ current,
792
+ setCurrent
793
+ };
794
+ };
795
+ var AnnouncementCenterUI2 = (props) => {
796
+ const { dataSource, current, setCurrent, onItemClick } = props;
797
+ return /* @__PURE__ */ jsx("div", { className: "oui-m-1 oui-rounded-xl oui-bg-base-9 oui-p-2", children: /* @__PURE__ */ jsx(
798
+ AnnouncementContent,
799
+ {
800
+ dataSource,
801
+ current,
802
+ onExpandToggle: setCurrent,
803
+ onItemClick,
804
+ showDivider: true
805
+ }
806
+ ) });
807
+ };
808
+ var AnnouncementCenterWidget = (props) => {
809
+ const { dataSource, current, setCurrent } = useAnnouncementCenterScript();
810
+ const onItemClick = useCallback(
811
+ (url) => {
812
+ if (!url)
813
+ return;
814
+ props.onRouteChange(url);
815
+ },
816
+ [props.onRouteChange]
817
+ );
818
+ return /* @__PURE__ */ jsx(
819
+ AnnouncementCenterUI2,
820
+ {
821
+ dataSource,
822
+ current,
823
+ setCurrent,
824
+ onItemClick
825
+ }
826
+ );
827
+ };
828
+ var AnnouncementCenterPage = (props) => {
829
+ return /* @__PURE__ */ jsx(
830
+ AnnouncementCenterWidget,
831
+ {
832
+ onRouteChange: (url) => {
833
+ if (!url)
834
+ return;
835
+ props.routerAdapter?.onRouteChange({
836
+ href: url,
837
+ name: url,
838
+ target: "_blank"
839
+ });
840
+ }
841
+ }
842
+ );
843
+ };
844
+
845
+ export { AnnouncementCenterPage, AnnouncementCenterUI, AnnouncementItem, NotificationUI, useAnnouncement };
846
+ //# sourceMappingURL=out.js.map
847
+ //# sourceMappingURL=index.mjs.map