@expcat/tigercat-react 0.2.27 → 0.3.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.
Files changed (87) hide show
  1. package/dist/chunk-4IO2M3ZJ.js +110 -0
  2. package/dist/{chunk-2UVQIL26.mjs → chunk-6DYS4PJT.mjs} +1 -1
  3. package/dist/chunk-6YKZAWNX.js +258 -0
  4. package/dist/chunk-73DMQ2SR.mjs +206 -0
  5. package/dist/chunk-FAZQT7YP.mjs +255 -0
  6. package/dist/{chunk-HRYBEBZC.js → chunk-GJKT2B56.js} +5 -1
  7. package/dist/{chunk-5XKYWZZZ.mjs → chunk-HGTF6A46.mjs} +5 -1
  8. package/dist/chunk-HT2BXCEM.js +264 -0
  9. package/dist/{chunk-6ZC7H22S.mjs → chunk-IAF24RKI.mjs} +1 -1
  10. package/dist/chunk-IYFSM2GA.mjs +141 -0
  11. package/dist/chunk-JAVDNFJD.js +144 -0
  12. package/dist/{chunk-P273E6XE.js → chunk-MQTHGPHF.js} +37 -21
  13. package/dist/chunk-OVWCTDAL.js +209 -0
  14. package/dist/{chunk-GIYBVWR4.mjs → chunk-OZLAGTZW.mjs} +38 -22
  15. package/dist/{chunk-OD2NNQD2.js → chunk-PBJ2J2B3.js} +2 -2
  16. package/dist/chunk-PVOQUXIB.mjs +189 -0
  17. package/dist/chunk-R67R3TVA.mjs +261 -0
  18. package/dist/{chunk-VR5OP4MO.js → chunk-UG3I4PCY.js} +2 -2
  19. package/dist/chunk-WKGCUR7O.mjs +107 -0
  20. package/dist/chunk-ZN2BZCTI.js +192 -0
  21. package/dist/components/ActivityFeed.d.mts +10 -0
  22. package/dist/components/ActivityFeed.d.ts +10 -0
  23. package/dist/components/ActivityFeed.js +23 -0
  24. package/dist/components/ActivityFeed.mjs +8 -0
  25. package/dist/components/AreaChart.js +4 -4
  26. package/dist/components/AreaChart.mjs +2 -2
  27. package/dist/components/BarChart.js +4 -4
  28. package/dist/components/BarChart.mjs +2 -2
  29. package/dist/components/ChatWindow.d.mts +12 -0
  30. package/dist/components/ChatWindow.d.ts +12 -0
  31. package/dist/components/ChatWindow.js +20 -0
  32. package/dist/components/ChatWindow.mjs +5 -0
  33. package/dist/components/CommentThread.d.mts +8 -0
  34. package/dist/components/CommentThread.d.ts +8 -0
  35. package/dist/components/CommentThread.js +21 -0
  36. package/dist/components/CommentThread.mjs +6 -0
  37. package/dist/components/DataTableWithToolbar.d.mts +51 -0
  38. package/dist/components/DataTableWithToolbar.d.ts +51 -0
  39. package/dist/components/DataTableWithToolbar.js +24 -0
  40. package/dist/components/DataTableWithToolbar.mjs +9 -0
  41. package/dist/components/DonutChart.js +5 -5
  42. package/dist/components/DonutChart.mjs +3 -3
  43. package/dist/components/Dropdown.js +4 -4
  44. package/dist/components/Dropdown.mjs +2 -2
  45. package/dist/components/DropdownItem.js +4 -4
  46. package/dist/components/DropdownItem.mjs +3 -3
  47. package/dist/components/FormItem.js +2 -2
  48. package/dist/components/FormItem.mjs +1 -1
  49. package/dist/components/FormWizard.d.mts +10 -0
  50. package/dist/components/FormWizard.d.ts +10 -0
  51. package/dist/components/FormWizard.js +19 -0
  52. package/dist/components/FormWizard.mjs +4 -0
  53. package/dist/components/LineChart.js +4 -4
  54. package/dist/components/LineChart.mjs +2 -2
  55. package/dist/components/NotificationCenter.d.mts +8 -0
  56. package/dist/components/NotificationCenter.d.ts +8 -0
  57. package/dist/components/NotificationCenter.js +23 -0
  58. package/dist/components/NotificationCenter.mjs +8 -0
  59. package/dist/components/PieChart.js +4 -4
  60. package/dist/components/PieChart.mjs +2 -2
  61. package/dist/components/RadarChart.js +4 -4
  62. package/dist/components/RadarChart.mjs +2 -2
  63. package/dist/components/ScatterChart.js +4 -4
  64. package/dist/components/ScatterChart.mjs +2 -2
  65. package/dist/components/Table.d.mts +1 -1
  66. package/dist/components/Table.d.ts +1 -1
  67. package/dist/components/Table.js +2 -2
  68. package/dist/components/Table.mjs +1 -1
  69. package/dist/index.d.mts +6 -0
  70. package/dist/index.d.ts +6 -0
  71. package/dist/index.js +197 -167
  72. package/dist/index.mjs +49 -43
  73. package/package.json +2 -2
  74. package/dist/{chunk-ZYF5GI2Q.js → chunk-4PTI6ZUK.js} +1 -1
  75. package/dist/{chunk-LIJLFLYE.js → chunk-4TWHENPT.js} +1 -1
  76. package/dist/{chunk-67WZRMD6.js → chunk-6E5UKM6O.js} +1 -1
  77. package/dist/{chunk-AFFSBNYB.mjs → chunk-AITVDDCE.mjs} +1 -1
  78. package/dist/{chunk-324UKFG2.mjs → chunk-IL2Y5RCX.mjs} +1 -1
  79. package/dist/{chunk-7SOL3UJ2.js → chunk-L63N3LCG.js} +1 -1
  80. package/dist/{chunk-E6GLWHRL.mjs → chunk-LZNG2HGC.mjs} +1 -1
  81. package/dist/{chunk-2VXA4YOP.js → chunk-N32MAX4A.js} +1 -1
  82. package/dist/{chunk-RKBNIEGF.mjs → chunk-PT4WLSTJ.mjs} +1 -1
  83. package/dist/{chunk-LWW2LXCP.js → chunk-SIB4EHB6.js} +1 -1
  84. package/dist/{chunk-2WLSB7K2.mjs → chunk-WYTHTJN3.mjs} +1 -1
  85. package/dist/{chunk-5QKBBGIA.mjs → chunk-YER7IQF4.mjs} +1 -1
  86. package/dist/{chunk-7IKJBQQV.mjs → chunk-YGOTPK2W.mjs} +1 -1
  87. package/dist/{chunk-KKHKQP6Z.js → chunk-ZUUG3WOL.js} +1 -1
@@ -0,0 +1,110 @@
1
+ 'use strict';
2
+
3
+ var chunkIQINYCU6_js = require('./chunk-IQINYCU6.js');
4
+ var chunkMKWXJZ3T_js = require('./chunk-MKWXJZ3T.js');
5
+ var chunk6MGEGOYJ_js = require('./chunk-6MGEGOYJ.js');
6
+ var chunk2TS6X5RA_js = require('./chunk-2TS6X5RA.js');
7
+ var chunkYYGTJKP5_js = require('./chunk-YYGTJKP5.js');
8
+ var chunkVO4WDK4K_js = require('./chunk-VO4WDK4K.js');
9
+ var chunkTZ26HQAW_js = require('./chunk-TZ26HQAW.js');
10
+ var react = require('react');
11
+ var tigercatCore = require('@expcat/tigercat-core');
12
+ var jsxRuntime = require('react/jsx-runtime');
13
+
14
+ var renderAction = (item, action, index) => {
15
+ const key = action.key ?? `${item.id}-action-${index}`;
16
+ return /* @__PURE__ */ jsxRuntime.jsx(
17
+ chunkMKWXJZ3T_js.Link,
18
+ {
19
+ size: "sm",
20
+ variant: "primary",
21
+ href: action.href,
22
+ target: action.target,
23
+ disabled: action.disabled,
24
+ onClick: () => action.onClick?.(item, action),
25
+ children: action.label
26
+ },
27
+ key
28
+ );
29
+ };
30
+ var ActivityFeed = ({
31
+ items = [],
32
+ groups,
33
+ groupBy,
34
+ groupOrder,
35
+ loading = false,
36
+ loadingText = "\u52A0\u8F7D\u4E2D...",
37
+ emptyText = "\u6682\u65E0\u52A8\u6001",
38
+ showAvatar = true,
39
+ showTime = true,
40
+ showGroupTitle = true,
41
+ renderItem,
42
+ renderGroupHeader,
43
+ className,
44
+ ...props
45
+ }) => {
46
+ const resolvedGroups = react.useMemo(
47
+ () => tigercatCore.buildActivityGroups(items, groups, groupBy, groupOrder),
48
+ [items, groups, groupBy, groupOrder]
49
+ );
50
+ const wrapperClasses = tigercatCore.classNames(
51
+ "tiger-activity-feed",
52
+ "flex",
53
+ "flex-col",
54
+ "gap-6",
55
+ "w-full",
56
+ className
57
+ );
58
+ const renderDefaultItem = (item, index, group) => {
59
+ if (renderItem) return renderItem(item, index, group);
60
+ const titleText = item.title ?? (typeof item.content === "string" || typeof item.content === "number" ? String(item.content) : "");
61
+ const descriptionText = item.description;
62
+ const timeText = showTime ? tigercatCore.formatActivityTime(item.time) : "";
63
+ const actionNodes = item.actions?.map(
64
+ (action, actionIndex) => renderAction(item, action, actionIndex)
65
+ );
66
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tiger-activity-item", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3 items-start", children: [
67
+ showAvatar && item.user ? /* @__PURE__ */ jsxRuntime.jsx(chunkTZ26HQAW_js.Avatar, { size: "sm", src: item.user.avatar, text: item.user.name, className: "shrink-0" }) : null,
68
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
69
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 mb-1", children: [
70
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
71
+ titleText ? /* @__PURE__ */ jsxRuntime.jsx(chunkYYGTJKP5_js.Text, { tag: "div", size: "sm", weight: "medium", className: "truncate", children: titleText }) : null,
72
+ item.status ? /* @__PURE__ */ jsxRuntime.jsx(chunk2TS6X5RA_js.Tag, { variant: item.status.variant ?? "default", size: "sm", className: "shrink-0", children: item.status.label }) : null
73
+ ] }),
74
+ timeText ? /* @__PURE__ */ jsxRuntime.jsx(chunkYYGTJKP5_js.Text, { tag: "div", size: "xs", color: "muted", className: "shrink-0 whitespace-nowrap", children: timeText }) : null
75
+ ] }),
76
+ descriptionText ? /* @__PURE__ */ jsxRuntime.jsx(chunkYYGTJKP5_js.Text, { tag: "div", size: "sm", color: "muted", className: "mb-2 break-words", children: descriptionText }) : null,
77
+ actionNodes?.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: actionNodes }) : null
78
+ ] })
79
+ ] }) });
80
+ };
81
+ if (loading) {
82
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrapperClasses, ...props, "data-tiger-activity-feed": true, children: /* @__PURE__ */ jsxRuntime.jsx(chunkVO4WDK4K_js.Card, { variant: "bordered", size: "sm", className: "tiger-activity-feed-loading", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-4", children: /* @__PURE__ */ jsxRuntime.jsx(chunk6MGEGOYJ_js.Loading, { text: loadingText }) }) }) });
83
+ }
84
+ if (resolvedGroups.length === 0) {
85
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrapperClasses, ...props, "data-tiger-activity-feed": true, children: /* @__PURE__ */ jsxRuntime.jsx(chunkVO4WDK4K_js.Card, { variant: "bordered", size: "sm", className: "tiger-activity-feed-empty", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ jsxRuntime.jsx(chunkYYGTJKP5_js.Text, { tag: "div", size: "sm", color: "muted", children: emptyText }) }) }) });
86
+ }
87
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrapperClasses, ...props, "data-tiger-activity-feed": true, children: resolvedGroups.map((group, groupIndex) => {
88
+ const headerNode = renderGroupHeader?.(group);
89
+ const groupTitle = group.title;
90
+ const timelineItems = tigercatCore.toActivityTimelineItems(group.items);
91
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
92
+ showGroupTitle && groupTitle ? headerNode ?? /* @__PURE__ */ jsxRuntime.jsx(chunkYYGTJKP5_js.Text, { tag: "div", size: "sm", weight: "medium", color: "muted", children: groupTitle }) : null,
93
+ /* @__PURE__ */ jsxRuntime.jsx(
94
+ chunkIQINYCU6_js.Timeline,
95
+ {
96
+ items: timelineItems,
97
+ renderItem: (timelineItem, index) => {
98
+ const activity = timelineItem.activity;
99
+ if (!activity) return null;
100
+ return renderDefaultItem(activity, index, group);
101
+ }
102
+ }
103
+ )
104
+ ] }, group.key ?? groupIndex);
105
+ }) });
106
+ };
107
+ var ActivityFeed_default = ActivityFeed;
108
+
109
+ exports.ActivityFeed = ActivityFeed;
110
+ exports.ActivityFeed_default = ActivityFeed_default;
@@ -1,4 +1,4 @@
1
- import { PieChart } from './chunk-E6GLWHRL.mjs';
1
+ import { PieChart } from './chunk-LZNG2HGC.mjs';
2
2
  import { useMemo } from 'react';
3
3
  import { getChartInnerRect, classNames } from '@expcat/tigercat-core';
4
4
  import { jsx } from 'react/jsx-runtime';
@@ -0,0 +1,258 @@
1
+ 'use strict';
2
+
3
+ var chunkHDDBBZQH_js = require('./chunk-HDDBBZQH.js');
4
+ var chunkOZLGNWET_js = require('./chunk-OZLGNWET.js');
5
+ var chunkA3DJSVTE_js = require('./chunk-A3DJSVTE.js');
6
+ var chunk6MGEGOYJ_js = require('./chunk-6MGEGOYJ.js');
7
+ var chunkYYGTJKP5_js = require('./chunk-YYGTJKP5.js');
8
+ var chunkVO4WDK4K_js = require('./chunk-VO4WDK4K.js');
9
+ var react = require('react');
10
+ var tigercatCore = require('@expcat/tigercat-core');
11
+ var jsxRuntime = require('react/jsx-runtime');
12
+
13
+ var getGroupKey = (group, index) => {
14
+ return group.key ?? group.title ?? index;
15
+ };
16
+ var filterItems = (items, filter) => {
17
+ return items.filter((item) => {
18
+ const isRead = Boolean(item.read);
19
+ if (filter === "read") return isRead;
20
+ if (filter === "unread") return !isRead;
21
+ return true;
22
+ });
23
+ };
24
+ var NotificationCenter = ({
25
+ items = [],
26
+ groups,
27
+ groupBy,
28
+ groupOrder,
29
+ activeGroupKey,
30
+ defaultActiveGroupKey,
31
+ readFilter,
32
+ defaultReadFilter = "all",
33
+ loading = false,
34
+ loadingText = "\u52A0\u8F7D\u4E2D...",
35
+ emptyText = "\u6682\u65E0\u901A\u77E5",
36
+ title = "\u901A\u77E5\u4E2D\u5FC3",
37
+ allLabel = "\u5168\u90E8",
38
+ unreadLabel = "\u672A\u8BFB",
39
+ readLabel = "\u5DF2\u8BFB",
40
+ markAllReadText = "\u5168\u90E8\u6807\u8BB0\u5DF2\u8BFB",
41
+ markReadText = "\u6807\u8BB0\u5DF2\u8BFB",
42
+ markUnreadText = "\u6807\u8BB0\u672A\u8BFB",
43
+ manageReadState = false,
44
+ onGroupChange,
45
+ onReadFilterChange,
46
+ onMarkAllRead,
47
+ onItemClick,
48
+ onItemReadChange,
49
+ className,
50
+ ...props
51
+ }) => {
52
+ const resolvedGroups = react.useMemo(
53
+ () => tigercatCore.buildNotificationGroups(items, groups, groupBy, groupOrder),
54
+ [items, groups, groupBy, groupOrder]
55
+ );
56
+ const firstGroupKey = react.useMemo(() => {
57
+ return resolvedGroups.length > 0 ? getGroupKey(resolvedGroups[0], 0) : void 0;
58
+ }, [resolvedGroups]);
59
+ const [internalGroupKey, setInternalGroupKey] = react.useState(
60
+ defaultActiveGroupKey
61
+ );
62
+ const [internalReadFilter, setInternalReadFilter] = react.useState(defaultReadFilter);
63
+ const currentGroupKey = activeGroupKey ?? internalGroupKey ?? firstGroupKey;
64
+ const currentReadFilter = readFilter ?? internalReadFilter;
65
+ react.useEffect(() => {
66
+ if (activeGroupKey !== void 0) return;
67
+ if (resolvedGroups.length === 0) {
68
+ setInternalGroupKey(void 0);
69
+ return;
70
+ }
71
+ const keys = resolvedGroups.map((group, index) => getGroupKey(group, index));
72
+ if (!keys.some((key) => key === currentGroupKey)) {
73
+ setInternalGroupKey(keys[0]);
74
+ }
75
+ }, [activeGroupKey, currentGroupKey, resolvedGroups]);
76
+ const currentGroup = react.useMemo(() => {
77
+ if (resolvedGroups.length === 0) return void 0;
78
+ if (currentGroupKey === void 0) return resolvedGroups[0];
79
+ const index = resolvedGroups.findIndex(
80
+ (group, groupIndex) => getGroupKey(group, groupIndex) === currentGroupKey
81
+ );
82
+ return index >= 0 ? resolvedGroups[index] : resolvedGroups[0];
83
+ }, [currentGroupKey, resolvedGroups]);
84
+ currentGroup?.items ?? [];
85
+ const [readStateOverrides, setReadStateOverrides] = react.useState(
86
+ () => /* @__PURE__ */ new Map()
87
+ );
88
+ react.useEffect(() => {
89
+ if (manageReadState) setReadStateOverrides(/* @__PURE__ */ new Map());
90
+ }, [items, manageReadState]);
91
+ const applyReadOverrides = (list) => {
92
+ if (!manageReadState || readStateOverrides.size === 0) return list;
93
+ return list.map((item) => {
94
+ const override = readStateOverrides.get(item.id);
95
+ return override !== void 0 ? { ...item, read: override } : item;
96
+ });
97
+ };
98
+ const effectiveGroups = react.useMemo(
99
+ () => resolvedGroups.map((group) => ({
100
+ ...group,
101
+ items: applyReadOverrides(group.items)
102
+ })),
103
+ // eslint-disable-next-line react-hooks/exhaustive-deps
104
+ [resolvedGroups, readStateOverrides]
105
+ );
106
+ const effectiveCurrentGroup = react.useMemo(() => {
107
+ if (effectiveGroups.length === 0) return void 0;
108
+ if (currentGroupKey === void 0) return effectiveGroups[0];
109
+ const index = effectiveGroups.findIndex(
110
+ (group, groupIndex) => getGroupKey(group, groupIndex) === currentGroupKey
111
+ );
112
+ return index >= 0 ? effectiveGroups[index] : effectiveGroups[0];
113
+ }, [currentGroupKey, effectiveGroups]);
114
+ const effectiveCurrentGroupItems = effectiveCurrentGroup?.items ?? [];
115
+ const effectiveItems = react.useMemo(() => applyReadOverrides(items), [items, readStateOverrides]);
116
+ const hasUnread = effectiveCurrentGroupItems.some((item) => !item.read);
117
+ const totalUnread = react.useMemo(() => {
118
+ const allItems = effectiveGroups.flatMap((group) => group.items);
119
+ if (allItems.length === 0) return effectiveItems.filter((item) => !item.read).length;
120
+ return allItems.filter((item) => !item.read).length;
121
+ }, [effectiveGroups, effectiveItems]);
122
+ const wrapperClasses = react.useMemo(
123
+ () => tigercatCore.classNames("tiger-notification-center", "w-full", "flex", "flex-col", className),
124
+ [className]
125
+ );
126
+ const handleGroupChange = (key) => {
127
+ if (activeGroupKey === void 0) {
128
+ setInternalGroupKey(key);
129
+ }
130
+ onGroupChange?.(key);
131
+ };
132
+ const handleReadFilterChange = (next) => {
133
+ if (readFilter === void 0) {
134
+ setInternalReadFilter(next);
135
+ }
136
+ onReadFilterChange?.(next);
137
+ };
138
+ const handleMarkAllRead = () => {
139
+ if (manageReadState) {
140
+ setReadStateOverrides((prev) => {
141
+ const next = new Map(prev);
142
+ effectiveCurrentGroupItems.forEach((item) => next.set(item.id, true));
143
+ return next;
144
+ });
145
+ }
146
+ onMarkAllRead?.(currentGroupKey, effectiveCurrentGroupItems);
147
+ };
148
+ const renderItem = (item, index) => {
149
+ const isRead = Boolean(item.read);
150
+ const timeText = item.time ? tigercatCore.formatActivityTime(item.time) : "";
151
+ return /* @__PURE__ */ jsxRuntime.jsxs(
152
+ "div",
153
+ {
154
+ className: tigercatCore.classNames(
155
+ "flex items-start gap-3 w-full py-0.5 transition-colors",
156
+ !isRead && "border-l-2 border-l-[var(--tiger-primary,#2563eb)] -ml-[2px] pl-[calc(0.75rem-2px)]"
157
+ ),
158
+ children: [
159
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
160
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline justify-between gap-2", children: [
161
+ /* @__PURE__ */ jsxRuntime.jsx(chunkYYGTJKP5_js.Text, { tag: "span", size: "sm", weight: isRead ? "normal" : "semibold", children: item.title }),
162
+ timeText ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-[var(--tiger-text-muted,#6b7280)] whitespace-nowrap flex-shrink-0", children: timeText }) : null
163
+ ] }),
164
+ item.description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-0.5 text-xs text-[var(--tiger-text-muted,#6b7280)] line-clamp-2 leading-relaxed", children: item.description }) : null
165
+ ] }),
166
+ /* @__PURE__ */ jsxRuntime.jsx(
167
+ chunkA3DJSVTE_js.Button,
168
+ {
169
+ size: "sm",
170
+ variant: "ghost",
171
+ onClick: (event) => {
172
+ event.stopPropagation();
173
+ if (manageReadState) {
174
+ setReadStateOverrides((prev) => {
175
+ const next = new Map(prev);
176
+ next.set(item.id, !isRead);
177
+ return next;
178
+ });
179
+ }
180
+ onItemReadChange?.(item, !isRead);
181
+ },
182
+ children: isRead ? markUnreadText : markReadText
183
+ }
184
+ )
185
+ ]
186
+ }
187
+ );
188
+ };
189
+ const renderList = (listItems) => /* @__PURE__ */ jsxRuntime.jsx(
190
+ chunkOZLGNWET_js.List,
191
+ {
192
+ dataSource: listItems,
193
+ split: true,
194
+ bordered: "divided",
195
+ hoverable: true,
196
+ emptyText,
197
+ onItemClick: (item, index) => onItemClick?.(item, index),
198
+ renderItem
199
+ }
200
+ );
201
+ const filterButtons = [
202
+ { key: "all", label: allLabel },
203
+ { key: "unread", label: unreadLabel },
204
+ { key: "read", label: readLabel }
205
+ ];
206
+ const content = loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx(chunk6MGEGOYJ_js.Loading, { text: loadingText }) }) : resolvedGroups.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "-mx-4 -mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(chunkHDDBBZQH_js.Tabs, { type: "line", size: "small", activeKey: currentGroupKey, onChange: handleGroupChange, children: resolvedGroups.map((group, index) => {
207
+ const effectiveGroup = effectiveGroups.find(
208
+ (eg, ei) => getGroupKey(eg, ei) === getGroupKey(group, index)
209
+ );
210
+ const groupItems = effectiveGroup?.items ?? group.items;
211
+ const unreadCount = groupItems.filter((item) => !item.read).length;
212
+ const labelBase = group.title || String(group.key ?? index);
213
+ const label = unreadCount > 0 ? `${labelBase} (${unreadCount})` : labelBase;
214
+ return /* @__PURE__ */ jsxRuntime.jsx(
215
+ chunkHDDBBZQH_js.TabPane,
216
+ {
217
+ tabKey: getGroupKey(group, index),
218
+ label,
219
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-[380px] overflow-y-auto", children: renderList(filterItems(groupItems, currentReadFilter)) })
220
+ },
221
+ String(getGroupKey(group, index))
222
+ );
223
+ }) }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "-mx-4 -mb-4 max-h-[380px] overflow-y-auto", children: renderList(filterItems(effectiveItems, currentReadFilter)) });
224
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrapperClasses, ...props, "data-tiger-notification-center": true, children: /* @__PURE__ */ jsxRuntime.jsx(
225
+ chunkVO4WDK4K_js.Card,
226
+ {
227
+ variant: "bordered",
228
+ className: "w-full",
229
+ header: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
230
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
231
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
232
+ /* @__PURE__ */ jsxRuntime.jsx(chunkYYGTJKP5_js.Text, { tag: "div", size: "base", weight: "bold", children: title }),
233
+ totalUnread > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex items-center justify-center min-w-[20px] h-5 px-1.5 text-xs font-semibold rounded-full bg-[var(--tiger-primary,#2563eb)] text-white", children: totalUnread }) : null
234
+ ] }),
235
+ /* @__PURE__ */ jsxRuntime.jsx(chunkA3DJSVTE_js.Button, { size: "sm", variant: "ghost", disabled: !hasUnread, onClick: handleMarkAllRead, children: markAllReadText })
236
+ ] }),
237
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex rounded-md border border-[var(--tiger-border,#e5e7eb)] overflow-hidden self-start", children: filterButtons.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
238
+ "button",
239
+ {
240
+ className: tigercatCore.classNames(
241
+ "px-3 py-1 text-xs font-medium transition-colors",
242
+ "border-r border-[var(--tiger-border,#e5e7eb)] last:border-r-0",
243
+ currentReadFilter === option.key ? "bg-[var(--tiger-primary,#2563eb)] text-white" : "bg-[var(--tiger-surface,#ffffff)] text-[var(--tiger-text-muted,#6b7280)] hover:bg-[var(--tiger-surface-muted,#f9fafb)]"
244
+ ),
245
+ onClick: () => handleReadFilterChange(option.key),
246
+ children: option.label
247
+ },
248
+ option.key
249
+ )) })
250
+ ] }),
251
+ children: content
252
+ }
253
+ ) });
254
+ };
255
+ var NotificationCenter_default = NotificationCenter;
256
+
257
+ exports.NotificationCenter = NotificationCenter;
258
+ exports.NotificationCenter_default = NotificationCenter_default;
@@ -0,0 +1,206 @@
1
+ import { Table } from './chunk-HGTF6A46.mjs';
2
+ import { Pagination } from './chunk-NDOYQK2R.mjs';
3
+ import { DropdownItem } from './chunk-IAF24RKI.mjs';
4
+ import { Dropdown } from './chunk-YGOTPK2W.mjs';
5
+ import { DropdownMenu } from './chunk-SIVJX7VU.mjs';
6
+ import { Input } from './chunk-6ZTCBQJ7.mjs';
7
+ import { Button } from './chunk-STEIWBMF.mjs';
8
+ import { useState, useEffect, useMemo } from 'react';
9
+ import { classNames } from '@expcat/tigercat-core';
10
+ import { jsxs, jsx } from 'react/jsx-runtime';
11
+
12
+ var resolveFilterLabel = (filter, value) => {
13
+ const option = filter.options.find((item) => item.value === value);
14
+ if (option) return `${filter.label}: ${option.label}`;
15
+ if (value !== null && value !== void 0 && value !== "") {
16
+ return `${filter.label}: ${String(value)}`;
17
+ }
18
+ return filter.placeholder ?? filter.label;
19
+ };
20
+ var DataTableWithToolbar = ({
21
+ toolbar,
22
+ onSearchChange,
23
+ onSearch,
24
+ onFiltersChange,
25
+ onBulkAction,
26
+ pagination = false,
27
+ onPageChange,
28
+ onPageSizeChange,
29
+ className,
30
+ tableClassName,
31
+ ...tableProps
32
+ }) => {
33
+ const [internalSearch, setInternalSearch] = useState(toolbar?.defaultSearchValue ?? "");
34
+ const [internalFilters, setInternalFilters] = useState(
35
+ () => {
36
+ const initial = {};
37
+ toolbar?.filters?.forEach((filter) => {
38
+ if (filter.value === void 0) {
39
+ initial[filter.key] = filter.defaultValue ?? null;
40
+ }
41
+ });
42
+ return initial;
43
+ }
44
+ );
45
+ useEffect(() => {
46
+ if (toolbar?.searchValue !== void 0) {
47
+ setInternalSearch(toolbar.searchValue ?? "");
48
+ }
49
+ }, [toolbar?.searchValue]);
50
+ useEffect(() => {
51
+ const filters = toolbar?.filters;
52
+ if (!filters) return;
53
+ setInternalFilters((prev) => {
54
+ const next = { ...prev };
55
+ filters.forEach((filter) => {
56
+ if (filter.value === void 0 && !(filter.key in next)) {
57
+ next[filter.key] = filter.defaultValue ?? null;
58
+ }
59
+ });
60
+ return next;
61
+ });
62
+ }, [toolbar?.filters]);
63
+ const searchValue = toolbar?.searchValue !== void 0 ? toolbar.searchValue : internalSearch;
64
+ const resolvedFilters = useMemo(() => {
65
+ const next = {};
66
+ toolbar?.filters?.forEach((filter) => {
67
+ next[filter.key] = filter.value !== void 0 ? filter.value : internalFilters[filter.key] ?? filter.defaultValue ?? null;
68
+ });
69
+ return next;
70
+ }, [toolbar?.filters, internalFilters]);
71
+ const hasSearch = Boolean(
72
+ toolbar && (toolbar.searchPlaceholder || toolbar.searchValue !== void 0 || toolbar.defaultSearchValue !== void 0 || toolbar.showSearchButton || toolbar.onSearchChange || toolbar.onSearch || onSearchChange || onSearch)
73
+ );
74
+ const hasFilters = Boolean(toolbar?.filters && toolbar.filters.length > 0);
75
+ const hasBulkActions = Boolean(toolbar?.bulkActions && toolbar.bulkActions.length > 0);
76
+ const selectedKeys = toolbar?.selectedKeys ?? tableProps.rowSelection?.selectedRowKeys ?? [];
77
+ const selectedCount = toolbar?.selectedCount ?? selectedKeys.length;
78
+ const bulkLabel = toolbar?.bulkActionsLabel ?? "\u5DF2\u9009\u62E9";
79
+ const wrapperClasses = useMemo(
80
+ () => classNames("tiger-data-table-with-toolbar flex flex-col gap-3", className),
81
+ [className]
82
+ );
83
+ const handleSearchChange = (value) => {
84
+ if (toolbar?.searchValue === void 0) {
85
+ setInternalSearch(value);
86
+ }
87
+ onSearchChange?.(value);
88
+ toolbar?.onSearchChange?.(value);
89
+ };
90
+ const handleSearchSubmit = () => {
91
+ onSearch?.(searchValue ?? "");
92
+ toolbar?.onSearch?.(searchValue ?? "");
93
+ };
94
+ const handleFilterSelect = (filter, value) => {
95
+ const nextFilters = {
96
+ ...resolvedFilters,
97
+ [filter.key]: value
98
+ };
99
+ if (filter.value === void 0) {
100
+ setInternalFilters((prev) => ({
101
+ ...prev,
102
+ [filter.key]: value
103
+ }));
104
+ }
105
+ onFiltersChange?.(nextFilters);
106
+ toolbar?.onFiltersChange?.(nextFilters);
107
+ };
108
+ const handleBulkAction = (action) => {
109
+ const keys = selectedKeys ?? [];
110
+ action.onClick?.(keys);
111
+ onBulkAction?.(action, keys);
112
+ toolbar?.onBulkAction?.(action, keys);
113
+ };
114
+ const renderToolbar = () => {
115
+ if (!hasSearch && !hasFilters && !hasBulkActions) return null;
116
+ return /* @__PURE__ */ jsxs("div", { className: "tiger-data-table-toolbar flex flex-wrap items-center gap-2", children: [
117
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
118
+ hasSearch ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
119
+ /* @__PURE__ */ jsx(
120
+ Input,
121
+ {
122
+ type: "search",
123
+ size: "sm",
124
+ value: searchValue,
125
+ placeholder: toolbar?.searchPlaceholder ?? "\u641C\u7D22",
126
+ onChange: (event) => handleSearchChange(String(event.currentTarget.value)),
127
+ onKeyDown: (event) => {
128
+ if (event.key === "Enter") {
129
+ handleSearchSubmit();
130
+ }
131
+ }
132
+ }
133
+ ),
134
+ toolbar?.showSearchButton ?? true ? /* @__PURE__ */ jsx(
135
+ Button,
136
+ {
137
+ size: "sm",
138
+ variant: "primary",
139
+ className: "whitespace-nowrap",
140
+ onClick: handleSearchSubmit,
141
+ disabled: !onSearch && !toolbar?.onSearch,
142
+ children: toolbar?.searchButtonText ?? "\u641C\u7D22"
143
+ }
144
+ ) : null
145
+ ] }) : null,
146
+ hasFilters ? toolbar?.filters?.map((filter) => {
147
+ const currentValue = resolvedFilters[filter.key];
148
+ const triggerLabel = resolveFilterLabel(filter, currentValue);
149
+ const clearable = filter.clearable !== false;
150
+ const clearLabel = filter.clearLabel ?? "\u5168\u90E8";
151
+ const isActive = currentValue !== null && currentValue !== void 0 && currentValue !== "";
152
+ return /* @__PURE__ */ jsxs(Dropdown, { trigger: "click", children: [
153
+ /* @__PURE__ */ jsx(
154
+ Button,
155
+ {
156
+ size: "sm",
157
+ variant: isActive ? "secondary" : "outline",
158
+ className: "whitespace-nowrap",
159
+ children: triggerLabel
160
+ }
161
+ ),
162
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
163
+ clearable ? /* @__PURE__ */ jsx(DropdownItem, { onClick: () => handleFilterSelect(filter, null), children: clearLabel }) : null,
164
+ filter.options.map((option) => /* @__PURE__ */ jsx(
165
+ DropdownItem,
166
+ {
167
+ onClick: () => handleFilterSelect(filter, option.value),
168
+ children: option.label
169
+ },
170
+ String(option.value)
171
+ ))
172
+ ] })
173
+ ] }, filter.key);
174
+ }) : null
175
+ ] }),
176
+ hasBulkActions ? /* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-2 flex-wrap", children: [
177
+ selectedCount > 0 ? /* @__PURE__ */ jsxs("span", { className: "text-sm text-[var(--tiger-text-muted,#6b7280)]", children: [
178
+ bulkLabel,
179
+ " ",
180
+ selectedCount,
181
+ " \u9879"
182
+ ] }) : null,
183
+ toolbar?.bulkActions?.map((action) => /* @__PURE__ */ jsx(
184
+ Button,
185
+ {
186
+ size: "sm",
187
+ variant: action.variant ?? "outline",
188
+ disabled: action.disabled || selectedCount === 0,
189
+ onClick: () => handleBulkAction(action),
190
+ children: action.label
191
+ },
192
+ action.key
193
+ ))
194
+ ] }) : null
195
+ ] });
196
+ };
197
+ const showPagination = pagination && typeof pagination === "object";
198
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClasses, "data-tiger-data-table-with-toolbar": true, children: [
199
+ renderToolbar(),
200
+ /* @__PURE__ */ jsx(Table, { ...tableProps, pagination: false, className: tableClassName }),
201
+ showPagination ? /* @__PURE__ */ jsx(Pagination, { ...pagination, onChange: onPageChange, onPageSizeChange }) : null
202
+ ] });
203
+ };
204
+ var DataTableWithToolbar_default = DataTableWithToolbar;
205
+
206
+ export { DataTableWithToolbar, DataTableWithToolbar_default };