@echothink-ui/activity 0.1.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 (39) hide show
  1. package/README.md +5 -0
  2. package/dist/components/ActivityFeed.d.ts +7 -0
  3. package/dist/components/ActivityTimeline.d.ts +6 -0
  4. package/dist/components/AlertBanner.d.ts +10 -0
  5. package/dist/components/ChangelogPanel.d.ts +6 -0
  6. package/dist/components/IncidentPanel.d.ts +6 -0
  7. package/dist/components/MentionList.d.ts +7 -0
  8. package/dist/components/NotificationCenter.d.ts +10 -0
  9. package/dist/components/NotificationItem.d.ts +8 -0
  10. package/dist/components/SubscriptionPreferences.d.ts +7 -0
  11. package/dist/components/SystemStatusBanner.d.ts +9 -0
  12. package/dist/components/WatcherList.d.ts +8 -0
  13. package/dist/components/helpers.d.ts +4 -0
  14. package/dist/components/types.d.ts +65 -0
  15. package/dist/index.cjs +944 -0
  16. package/dist/index.cjs.map +1 -0
  17. package/dist/index.css +711 -0
  18. package/dist/index.css.map +1 -0
  19. package/dist/index.d.ts +16 -0
  20. package/dist/index.js +904 -0
  21. package/dist/index.js.map +1 -0
  22. package/package.json +43 -0
  23. package/src/components/ActivityFeed.tsx +83 -0
  24. package/src/components/ActivityTimeline.tsx +178 -0
  25. package/src/components/AlertBanner.tsx +69 -0
  26. package/src/components/ChangelogPanel.tsx +100 -0
  27. package/src/components/IncidentPanel.tsx +82 -0
  28. package/src/components/MentionList.tsx +85 -0
  29. package/src/components/NotificationCenter.tsx +117 -0
  30. package/src/components/NotificationItem.tsx +99 -0
  31. package/src/components/SubscriptionPreferences.test.tsx +64 -0
  32. package/src/components/SubscriptionPreferences.tsx +140 -0
  33. package/src/components/SystemStatusBanner.tsx +46 -0
  34. package/src/components/WatcherList.test.tsx +50 -0
  35. package/src/components/WatcherList.tsx +122 -0
  36. package/src/components/helpers.ts +15 -0
  37. package/src/components/types.ts +71 -0
  38. package/src/index.tsx +31 -0
  39. package/src/styles.css +854 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,944 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.tsx
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ ActivityComponentNames: () => ActivityComponentNames,
34
+ ActivityFeed: () => ActivityFeed,
35
+ ActivityTimeline: () => ActivityTimeline,
36
+ AlertBanner: () => AlertBanner,
37
+ AuditLogTable: () => import_data.AuditLogTable,
38
+ ChangelogPanel: () => ChangelogPanel,
39
+ IncidentPanel: () => IncidentPanel,
40
+ MentionList: () => MentionList,
41
+ NotificationCenter: () => NotificationCenter,
42
+ NotificationItem: () => NotificationItem,
43
+ SubscriptionPreferences: () => SubscriptionPreferences,
44
+ SystemStatusBanner: () => SystemStatusBanner,
45
+ WatcherList: () => WatcherList
46
+ });
47
+ module.exports = __toCommonJS(index_exports);
48
+
49
+ // src/components/NotificationCenter.tsx
50
+ var import_core2 = require("@echothink-ui/core");
51
+
52
+ // src/components/NotificationItem.tsx
53
+ var import_core = require("@echothink-ui/core");
54
+
55
+ // src/components/helpers.ts
56
+ function severityToCore(severity) {
57
+ if (severity === "error" || severity === "danger") return "danger";
58
+ if (severity === "success") return "success";
59
+ if (severity === "warning") return "warning";
60
+ return "info";
61
+ }
62
+ function dateGroupKey(value) {
63
+ const date = new Date(value);
64
+ if (!Number.isFinite(date.valueOf())) return value;
65
+ return date.toISOString().slice(0, 10);
66
+ }
67
+
68
+ // src/components/NotificationItem.tsx
69
+ var import_jsx_runtime = require("react/jsx-runtime");
70
+ function NotificationItem({
71
+ notification,
72
+ onRead,
73
+ onClick,
74
+ className,
75
+ title: _title,
76
+ subtitle: _subtitle,
77
+ description: _description,
78
+ eyebrow: _eyebrow,
79
+ density: _density,
80
+ status: _status,
81
+ severity: _severity,
82
+ loading: _loading,
83
+ empty: _empty,
84
+ error: _error,
85
+ items: _items,
86
+ actions: _actions,
87
+ metadata: _metadata,
88
+ footer: _footer,
89
+ ...props
90
+ }) {
91
+ const severity = severityToCore(notification.severity);
92
+ const mainContent = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
93
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Badge, { className: "eth-activity-notification-item__severity", severity, children: notification.severity }),
94
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "eth-activity-notification-item__content", children: [
95
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { className: "eth-activity-notification-item__title", children: notification.title }),
96
+ notification.body ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "eth-activity-notification-item__body", children: notification.body }) : null
97
+ ] }),
98
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
99
+ "time",
100
+ {
101
+ className: "eth-activity-notification-item__time",
102
+ dateTime: dateTimeValue(notification.createdAt),
103
+ children: formatTimestamp(notification.createdAt)
104
+ }
105
+ )
106
+ ] });
107
+ const hasActions = Boolean(!notification.read && onRead || notification.actions?.length);
108
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
109
+ "article",
110
+ {
111
+ ...props,
112
+ className: [
113
+ "eth-activity-notification-item",
114
+ notification.read ? "eth-activity-notification-item--read" : void 0,
115
+ className
116
+ ].filter(Boolean).join(" "),
117
+ "data-eth-component": "NotificationItem",
118
+ "data-severity": severity,
119
+ children: [
120
+ onClick ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "eth-activity-notification-item__main", onClick, children: mainContent }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "eth-activity-notification-item__main", children: mainContent }),
121
+ hasActions ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "eth-activity-notification-item__actions", children: [
122
+ !notification.read && onRead ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Button, { type: "button", intent: "ghost", density: "compact", onClick: onRead, children: "Mark read" }) : null,
123
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.ActionGroup, { actions: notification.actions })
124
+ ] }) : null
125
+ ]
126
+ }
127
+ );
128
+ }
129
+ function dateTimeValue(value) {
130
+ const date = new Date(value);
131
+ return Number.isFinite(date.valueOf()) ? date.toISOString() : void 0;
132
+ }
133
+ function formatTimestamp(value) {
134
+ const date = new Date(value);
135
+ if (!Number.isFinite(date.valueOf())) return value;
136
+ const iso = date.toISOString();
137
+ return `${iso.slice(11, 16)} UTC`;
138
+ }
139
+
140
+ // src/components/NotificationCenter.tsx
141
+ var import_jsx_runtime2 = require("react/jsx-runtime");
142
+ function NotificationCenter({
143
+ notifications,
144
+ unreadCount,
145
+ onMarkRead,
146
+ onMarkAllRead,
147
+ onDismiss,
148
+ title,
149
+ className,
150
+ role,
151
+ "aria-label": ariaLabel,
152
+ ...props
153
+ }) {
154
+ const groups = groupByDate(notifications);
155
+ const unreadTotal = unreadCount ?? notifications.filter((item) => !item.read).length;
156
+ const displayTitle = title ?? "Notifications";
157
+ const regionLabel = ariaLabel ?? (typeof displayTitle === "string" ? displayTitle : "Notification center");
158
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
159
+ import_core2.Surface,
160
+ {
161
+ ...props,
162
+ title: displayTitle,
163
+ subtitle: `${unreadTotal} unread`,
164
+ className: ["eth-activity-notification-center", className].filter(Boolean).join(" "),
165
+ "data-eth-component": "NotificationCenter",
166
+ role: role ?? "region",
167
+ "aria-label": regionLabel,
168
+ children: [
169
+ onMarkAllRead ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "eth-activity-notification-center__toolbar", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
170
+ import_core2.Button,
171
+ {
172
+ type: "button",
173
+ intent: "secondary",
174
+ density: "compact",
175
+ disabled: unreadTotal === 0,
176
+ onClick: onMarkAllRead,
177
+ children: "Mark all read"
178
+ }
179
+ ) }) : null,
180
+ notifications.length ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "eth-activity-notification-center__groups", children: groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "eth-activity-notification-center__group", children: [
181
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: formatGroupLabel(group.date) }),
182
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ol", { className: "eth-activity-notification-center__items", children: group.items.map((notification) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { className: "eth-activity-notification-center__row", children: [
183
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
184
+ NotificationItem,
185
+ {
186
+ notification,
187
+ onRead: onMarkRead && !notification.read ? () => onMarkRead(notification.id) : void 0
188
+ }
189
+ ),
190
+ onDismiss ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
191
+ import_core2.Button,
192
+ {
193
+ type: "button",
194
+ intent: "ghost",
195
+ density: "compact",
196
+ onClick: () => onDismiss(notification.id),
197
+ children: "Dismiss"
198
+ }
199
+ ) : null
200
+ ] }, notification.id)) })
201
+ ] }, group.date)) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "eth-activity-notification-center__empty", children: "No notifications." })
202
+ ]
203
+ }
204
+ );
205
+ }
206
+ function groupByDate(notifications) {
207
+ const groups = /* @__PURE__ */ new Map();
208
+ for (const notification of notifications) {
209
+ const key = groupKey(notification.createdAt);
210
+ groups.set(key, [...groups.get(key) ?? [], notification]);
211
+ }
212
+ return Array.from(groups, ([date, items]) => ({ date, items }));
213
+ }
214
+ function groupKey(value) {
215
+ const date = new Date(value);
216
+ return Number.isFinite(date.valueOf()) ? date.toISOString().slice(0, 10) : "Recent";
217
+ }
218
+ function formatGroupLabel(value) {
219
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) return value;
220
+ return new Intl.DateTimeFormat(void 0, {
221
+ day: "numeric",
222
+ month: "short",
223
+ timeZone: "UTC",
224
+ weekday: "short",
225
+ year: "numeric"
226
+ }).format(/* @__PURE__ */ new Date(`${value}T00:00:00Z`));
227
+ }
228
+
229
+ // src/components/ActivityFeed.tsx
230
+ var import_core3 = require("@echothink-ui/core");
231
+ var import_jsx_runtime3 = require("react/jsx-runtime");
232
+ function ActivityFeed({ events, streaming, title, className, ...props }) {
233
+ const hasEvents = events.length > 0;
234
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
235
+ import_core3.Surface,
236
+ {
237
+ ...props,
238
+ title: title ?? "Activity",
239
+ className: ["eth-activity-feed", className].filter(Boolean).join(" "),
240
+ "data-eth-component": "ActivityFeed",
241
+ children: [
242
+ streaming ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "eth-activity-feed__status", "aria-label": "Streaming activity", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core3.Badge, { severity: "success", children: "Streaming" }) }) : null,
243
+ hasEvents ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ol", { className: "eth-activity-feed__events", "aria-live": streaming ? "polite" : void 0, children: events.map((event) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
244
+ "li",
245
+ {
246
+ className: `eth-activity-feed__event eth-activity-feed__event--${verbClass(event.verb)}`,
247
+ children: [
248
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "eth-activity-feed__icon", "aria-hidden": true, children: iconForVerb(event.verb) }),
249
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "eth-activity-feed__body", children: [
250
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "eth-activity-feed__summary", children: [
251
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: event.actor }),
252
+ " ",
253
+ event.verb,
254
+ " ",
255
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: event.objectLabel }),
256
+ event.targetLabel ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
257
+ " ",
258
+ "in ",
259
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: event.targetLabel })
260
+ ] }) : null
261
+ ] }),
262
+ event.details ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "eth-activity-feed__details", children: event.details }) : null,
263
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("time", { className: "eth-activity-feed__time", dateTime: dateTimeValue2(event.createdAt), children: formatTimestamp2(event.createdAt) })
264
+ ] })
265
+ ]
266
+ },
267
+ event.id
268
+ )) }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "eth-activity-feed__empty", children: "No activity yet." })
269
+ ]
270
+ }
271
+ );
272
+ }
273
+ function iconForVerb(verb) {
274
+ const normalized = verb.toLowerCase();
275
+ if (normalized.includes("create") || normalized.includes("add")) return "+";
276
+ if (normalized.includes("delete") || normalized.includes("remove")) return "-";
277
+ if (normalized.includes("approve")) return "\u2713";
278
+ if (normalized.includes("fail") || normalized.includes("reject")) return "!";
279
+ return "\u2022";
280
+ }
281
+ function verbClass(verb) {
282
+ return verb.toLowerCase().replace(/[^a-z0-9]+/g, "-") || "event";
283
+ }
284
+ function dateTimeValue2(value) {
285
+ const date = new Date(value);
286
+ return Number.isFinite(date.valueOf()) ? date.toISOString() : value;
287
+ }
288
+ function formatTimestamp2(value) {
289
+ const date = new Date(value);
290
+ if (!Number.isFinite(date.valueOf())) return value;
291
+ const iso = date.toISOString();
292
+ return `${iso.slice(0, 10)} ${iso.slice(11, 16)} UTC`;
293
+ }
294
+
295
+ // src/components/ActivityTimeline.tsx
296
+ var import_core4 = require("@echothink-ui/core");
297
+ var import_jsx_runtime4 = require("react/jsx-runtime");
298
+ function ActivityTimeline({
299
+ events = [],
300
+ title,
301
+ subtitle,
302
+ className,
303
+ role,
304
+ "aria-label": ariaLabel,
305
+ ...props
306
+ }) {
307
+ const groups = groupEvents(events);
308
+ const eventCount = events.length;
309
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
310
+ import_core4.Surface,
311
+ {
312
+ ...props,
313
+ title: title ?? "Timeline",
314
+ subtitle: subtitle ?? summaryText(groups.length, eventCount),
315
+ className: ["eth-activity-timeline", className].filter(Boolean).join(" "),
316
+ "data-eth-component": "ActivityTimeline",
317
+ role: role ?? "region",
318
+ "aria-label": ariaLabel ?? "Activity timeline",
319
+ children: eventCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "eth-activity-timeline__content", children: groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "eth-activity-timeline__group", children: [
320
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "eth-activity-timeline__group-header", children: [
321
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: formatGroupLabel2(group.date) }),
322
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: summaryText(0, group.events.length) })
323
+ ] }),
324
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ol", { className: "eth-activity-timeline__events", children: group.events.map((event) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
325
+ "li",
326
+ {
327
+ className: `eth-activity-timeline__event eth-activity-timeline__event--${verbClass2(event.verb)}`,
328
+ children: [
329
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "eth-activity-timeline__marker", "aria-hidden": true, children: iconForVerb2(event.verb) }),
330
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("article", { className: "eth-activity-timeline__card", children: [
331
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "eth-activity-timeline__event-header", children: [
332
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core4.Badge, { severity: severityForVerb(event.verb), children: kindLabel(event.verb) }),
333
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("time", { dateTime: dateTimeValue3(event.createdAt), children: formatTimestamp3(event.createdAt) })
334
+ ] }),
335
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "eth-activity-timeline__summary", children: [
336
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: event.actor }),
337
+ " ",
338
+ event.verb,
339
+ " ",
340
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: event.objectLabel }),
341
+ event.targetLabel ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
342
+ " ",
343
+ "in ",
344
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: event.targetLabel })
345
+ ] }) : null
346
+ ] }),
347
+ event.details ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "eth-activity-timeline__details", children: event.details }) : null
348
+ ] })
349
+ ]
350
+ },
351
+ event.id
352
+ )) })
353
+ ] }, group.date)) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "eth-activity-timeline__empty", children: "No activity yet." })
354
+ }
355
+ );
356
+ }
357
+ function groupEvents(events) {
358
+ const groups = /* @__PURE__ */ new Map();
359
+ const sortedEvents = events.map((event, index) => ({ event, index })).sort((a, b) => compareEvents(a, b)).map(({ event }) => event);
360
+ for (const event of sortedEvents) {
361
+ const key = dateGroupKey(event.createdAt);
362
+ groups.set(key, [...groups.get(key) ?? [], event]);
363
+ }
364
+ return Array.from(groups, ([date, groupedEvents]) => ({ date, events: groupedEvents }));
365
+ }
366
+ function compareEvents(a, b) {
367
+ const aTime = timestampValue(a.event.createdAt);
368
+ const bTime = timestampValue(b.event.createdAt);
369
+ if (aTime !== null && bTime !== null && aTime !== bTime) return bTime - aTime;
370
+ if (aTime !== null && bTime === null) return -1;
371
+ if (aTime === null && bTime !== null) return 1;
372
+ return a.index - b.index;
373
+ }
374
+ function timestampValue(value) {
375
+ const timestamp = new Date(value).getTime();
376
+ return Number.isFinite(timestamp) ? timestamp : null;
377
+ }
378
+ function dateTimeValue3(value) {
379
+ const date = new Date(value);
380
+ return Number.isFinite(date.valueOf()) ? date.toISOString() : value;
381
+ }
382
+ function formatGroupLabel2(value) {
383
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) return value;
384
+ return new Intl.DateTimeFormat(void 0, {
385
+ day: "numeric",
386
+ month: "short",
387
+ timeZone: "UTC",
388
+ weekday: "short",
389
+ year: "numeric"
390
+ }).format(/* @__PURE__ */ new Date(`${value}T00:00:00Z`));
391
+ }
392
+ function formatTimestamp3(value) {
393
+ const date = new Date(value);
394
+ if (!Number.isFinite(date.valueOf())) return value;
395
+ const iso = date.toISOString();
396
+ return `${iso.slice(11, 16)} UTC`;
397
+ }
398
+ function summaryText(groupCount, eventCount) {
399
+ const eventLabel = `${eventCount} ${eventCount === 1 ? "event" : "events"}`;
400
+ if (groupCount <= 0) return eventLabel;
401
+ return `${eventLabel} across ${groupCount} ${groupCount === 1 ? "day" : "days"}`;
402
+ }
403
+ function iconForVerb2(verb) {
404
+ const normalized = verb.toLowerCase();
405
+ if (normalized.includes("approve")) return "\u2713";
406
+ if (normalized.includes("draft") || normalized.includes("create") || normalized.includes("add")) {
407
+ return "+";
408
+ }
409
+ if (normalized.includes("comment")) return "\u2026";
410
+ if (normalized.includes("fail") || normalized.includes("reject")) return "!";
411
+ return "\u2022";
412
+ }
413
+ function kindLabel(verb) {
414
+ const normalized = verb.trim().toLowerCase();
415
+ if (normalized.includes("approve")) return "Approval";
416
+ if (normalized.includes("draft")) return "Draft";
417
+ if (normalized.includes("comment")) return "Comment";
418
+ if (normalized.includes("create") || normalized.includes("add")) return "Created";
419
+ if (normalized.includes("fail") || normalized.includes("reject")) return "Attention";
420
+ return "Update";
421
+ }
422
+ function severityForVerb(verb) {
423
+ const normalized = verb.toLowerCase();
424
+ if (normalized.includes("approve")) return "success";
425
+ if (normalized.includes("fail") || normalized.includes("reject")) return "danger";
426
+ if (normalized.includes("comment")) return "info";
427
+ return "neutral";
428
+ }
429
+ function verbClass2(verb) {
430
+ return verb.toLowerCase().replace(/[^a-z0-9]+/g, "-") || "event";
431
+ }
432
+
433
+ // src/components/AlertBanner.tsx
434
+ var import_core5 = require("@echothink-ui/core");
435
+ var import_jsx_runtime5 = require("react/jsx-runtime");
436
+ function AlertBanner({
437
+ severity,
438
+ title,
439
+ description,
440
+ onDismiss,
441
+ actions,
442
+ className,
443
+ role,
444
+ ...props
445
+ }) {
446
+ const coreSeverity = severityToCore(severity);
447
+ const hasActions = Boolean(actions?.length || onDismiss);
448
+ const ariaLive = props["aria-live"] ?? (coreSeverity === "danger" ? "assertive" : "polite");
449
+ const dataEthComponent = props["data-eth-component"] ?? "AlertBanner";
450
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
451
+ "section",
452
+ {
453
+ ...props,
454
+ className: [
455
+ "eth-activity-alert-banner",
456
+ `eth-activity-alert-banner--${coreSeverity}`,
457
+ className
458
+ ].filter(Boolean).join(" "),
459
+ "data-eth-component": dataEthComponent,
460
+ role: role ?? (coreSeverity === "danger" ? "alert" : "status"),
461
+ "aria-live": ariaLive,
462
+ children: [
463
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "eth-activity-alert-banner__notice", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_core5.InlineNotification, { severity: coreSeverity, title, children: description }) }),
464
+ hasActions ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "eth-activity-alert-banner__actions", children: [
465
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_core5.ActionGroup, { actions }),
466
+ onDismiss ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_core5.Button, { type: "button", intent: "ghost", density: "compact", onClick: onDismiss, children: "Dismiss" }) : null
467
+ ] }) : null
468
+ ]
469
+ }
470
+ );
471
+ }
472
+
473
+ // src/components/SystemStatusBanner.tsx
474
+ var import_jsx_runtime6 = require("react/jsx-runtime");
475
+ function SystemStatusBanner({
476
+ status,
477
+ title,
478
+ description,
479
+ actions,
480
+ onDismiss,
481
+ className
482
+ }) {
483
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
484
+ AlertBanner,
485
+ {
486
+ severity: severityForStatus(status),
487
+ title: title ?? defaultTitleForStatus(status),
488
+ description,
489
+ actions,
490
+ onDismiss,
491
+ className: ["eth-activity-system-status-banner", className].filter(Boolean).join(" "),
492
+ "data-eth-component": "SystemStatusBanner"
493
+ }
494
+ );
495
+ }
496
+ function defaultTitleForStatus(status) {
497
+ if (status === "operational") return "System operational";
498
+ if (status === "degraded") return "System degraded";
499
+ if (status === "maintenance") return "Scheduled maintenance";
500
+ return "System unavailable";
501
+ }
502
+ function severityForStatus(status) {
503
+ if (status === "operational") return "success";
504
+ if (status === "degraded" || status === "maintenance") return "warning";
505
+ return "error";
506
+ }
507
+
508
+ // src/components/IncidentPanel.tsx
509
+ var import_core6 = require("@echothink-ui/core");
510
+ var import_jsx_runtime7 = require("react/jsx-runtime");
511
+ function IncidentPanel({ incidents, title, className, ...props }) {
512
+ const hasIncidents = incidents.length > 0;
513
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
514
+ import_core6.Surface,
515
+ {
516
+ ...props,
517
+ title: title ?? "Incidents",
518
+ className: ["eth-activity-incident-panel", className].filter(Boolean).join(" "),
519
+ "data-eth-component": "IncidentPanel",
520
+ children: hasIncidents ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "eth-activity-incident-panel__list", role: "list", children: incidents.map((incident) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
521
+ "article",
522
+ {
523
+ className: "eth-activity-incident-panel__incident",
524
+ "data-severity": incident.severity ? severityToCore(incident.severity) : void 0,
525
+ role: "listitem",
526
+ "aria-label": incident.title,
527
+ children: [
528
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("header", { className: "eth-activity-incident-panel__incident-header", children: [
529
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "eth-activity-incident-panel__summary", children: [
530
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { children: incident.title }),
531
+ incident.description ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { children: incident.description }) : null
532
+ ] }),
533
+ incident.severity ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
534
+ import_core6.Badge,
535
+ {
536
+ className: "eth-activity-incident-panel__severity",
537
+ severity: severityToCore(incident.severity),
538
+ children: formatIncidentLabel(incident.severity)
539
+ }
540
+ ) : null
541
+ ] }),
542
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("dl", { className: "eth-activity-incident-panel__metadata", children: [
543
+ incident.status ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
544
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dt", { children: "Status" }),
545
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
546
+ "span",
547
+ {
548
+ className: "eth-activity-incident-panel__status",
549
+ "data-status": incident.status,
550
+ children: [
551
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": "true" }),
552
+ formatIncidentLabel(incident.status)
553
+ ]
554
+ }
555
+ ) })
556
+ ] }) : null,
557
+ incident.startedAt ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
558
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dt", { children: "Started" }),
559
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("time", { children: incident.startedAt }) })
560
+ ] }) : null
561
+ ] })
562
+ ]
563
+ },
564
+ incident.id
565
+ )) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "eth-activity-incident-panel__empty", children: "No active incidents." })
566
+ }
567
+ );
568
+ }
569
+ function formatIncidentLabel(value) {
570
+ return value.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
571
+ }
572
+
573
+ // src/components/ChangelogPanel.tsx
574
+ var import_core7 = require("@echothink-ui/core");
575
+ var import_jsx_runtime8 = require("react/jsx-runtime");
576
+ function ChangelogPanel({
577
+ entries,
578
+ title,
579
+ subtitle,
580
+ className,
581
+ role,
582
+ "aria-label": ariaLabel,
583
+ ...props
584
+ }) {
585
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
586
+ import_core7.Surface,
587
+ {
588
+ ...props,
589
+ title: title ?? "Changelog",
590
+ subtitle: subtitle ?? changelogSummary(entries),
591
+ className: ["eth-activity-changelog", className].filter(Boolean).join(" "),
592
+ "data-eth-component": "ChangelogPanel",
593
+ role: role ?? "region",
594
+ "aria-label": ariaLabel ?? "Product changelog",
595
+ children: entries.length ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ol", { className: "eth-activity-changelog__releases", children: entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("li", { className: "eth-activity-changelog__release", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
596
+ "article",
597
+ {
598
+ className: "eth-activity-changelog__entry",
599
+ "aria-label": `Version ${entry.version}`,
600
+ children: [
601
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("header", { className: "eth-activity-changelog__entry-header", children: [
602
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
603
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { children: entry.version }),
604
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("time", { dateTime: dateTimeValue4(entry.date), children: entry.date })
605
+ ] }),
606
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "eth-activity-changelog__entry-count", children: pluralize(entry.changes.length, "change") })
607
+ ] }),
608
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { className: "eth-activity-changelog__changes", children: entry.changes.map((change, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
609
+ "li",
610
+ {
611
+ className: `eth-activity-changelog__change eth-activity-changelog__change--${change.type}`,
612
+ children: [
613
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_core7.Badge, { severity: severityForChange(change.type), children: changeLabel(change.type) }),
614
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: change.summary })
615
+ ]
616
+ },
617
+ `${change.type}-${index}`
618
+ )) })
619
+ ]
620
+ }
621
+ ) }, entry.id)) }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "eth-activity-changelog__empty", children: "No release notes published yet." })
622
+ }
623
+ );
624
+ }
625
+ function severityForChange(type) {
626
+ if (type === "added") return "success";
627
+ if (type === "fixed") return "info";
628
+ if (type === "removed") return "danger";
629
+ return "warning";
630
+ }
631
+ function changeLabel(type) {
632
+ const labels = {
633
+ added: "Added",
634
+ changed: "Changed",
635
+ fixed: "Fixed",
636
+ removed: "Removed"
637
+ };
638
+ return labels[type];
639
+ }
640
+ function changelogSummary(entries) {
641
+ if (!entries.length) return "No releases published";
642
+ const changeCount = entries.reduce((count, entry) => count + entry.changes.length, 0);
643
+ return `${pluralize(entries.length, "release")} \xB7 ${pluralize(changeCount, "change")}`;
644
+ }
645
+ function pluralize(count, label) {
646
+ return `${count} ${label}${count === 1 ? "" : "s"}`;
647
+ }
648
+ function dateTimeValue4(value) {
649
+ const date = new Date(value);
650
+ return Number.isFinite(date.valueOf()) ? date.toISOString().slice(0, 10) : void 0;
651
+ }
652
+
653
+ // src/components/SubscriptionPreferences.tsx
654
+ var React = __toESM(require("react"), 1);
655
+ var import_core8 = require("@echothink-ui/core");
656
+ var import_jsx_runtime9 = require("react/jsx-runtime");
657
+ function SubscriptionPreferences({
658
+ categories,
659
+ onToggle,
660
+ title,
661
+ className,
662
+ role,
663
+ "aria-label": ariaLabel,
664
+ ...props
665
+ }) {
666
+ const displayTitle = title ?? "Notification preferences";
667
+ const panelLabel = ariaLabel ?? (typeof displayTitle === "string" ? displayTitle : void 0);
668
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
669
+ import_core8.Surface,
670
+ {
671
+ ...props,
672
+ title: displayTitle,
673
+ role: role ?? (panelLabel ? "region" : void 0),
674
+ "aria-label": panelLabel,
675
+ className: ["eth-activity-subscription-preferences", className].filter(Boolean).join(" "),
676
+ "data-eth-component": "SubscriptionPreferences",
677
+ children: categories.length ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "eth-activity-subscription-preferences__categories", children: categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SubscriptionCategoryGroup, { category, onToggle }, category.id)) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "eth-activity-subscription-preferences__empty", role: "status", children: "No notification categories configured." })
678
+ }
679
+ );
680
+ }
681
+ function SubscriptionCategoryGroup({
682
+ category,
683
+ onToggle
684
+ }) {
685
+ const headingId = React.useId();
686
+ const descriptionId = category.description ? `${headingId}-description` : void 0;
687
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
688
+ "section",
689
+ {
690
+ className: "eth-activity-subscription-preferences__category",
691
+ role: "group",
692
+ "aria-labelledby": headingId,
693
+ "aria-describedby": descriptionId,
694
+ children: [
695
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("header", { className: "eth-activity-subscription-preferences__category-header", children: [
696
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { id: headingId, children: category.label }),
697
+ category.description ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
698
+ "p",
699
+ {
700
+ id: descriptionId,
701
+ className: "eth-activity-subscription-preferences__category-description",
702
+ children: category.description
703
+ }
704
+ ) : null
705
+ ] }),
706
+ category.channels.length ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "eth-activity-subscription-preferences__channels", children: category.channels.map((channel) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
707
+ SubscriptionChannelRow,
708
+ {
709
+ category,
710
+ channel,
711
+ onToggle
712
+ },
713
+ channel.id
714
+ )) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "eth-activity-subscription-preferences__channel-empty", children: "No channels configured." })
715
+ ]
716
+ }
717
+ );
718
+ }
719
+ function SubscriptionChannelRow({
720
+ category,
721
+ channel,
722
+ onToggle
723
+ }) {
724
+ const accessibleLabel = `${category.label} ${channel.label}`;
725
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
726
+ "div",
727
+ {
728
+ className: [
729
+ "eth-activity-subscription-preferences__channel",
730
+ channel.disabled ? "eth-activity-subscription-preferences__channel--disabled" : void 0
731
+ ].filter(Boolean).join(" "),
732
+ children: [
733
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "eth-activity-subscription-preferences__channel-copy", children: [
734
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "eth-activity-subscription-preferences__channel-label", children: channel.label }),
735
+ channel.description ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "eth-activity-subscription-preferences__channel-description", children: channel.description }) : null
736
+ ] }),
737
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
738
+ import_core8.Toggle,
739
+ {
740
+ id: `eth-subscription-${safeId(category.id)}-${safeId(channel.id)}`,
741
+ label: accessibleLabel,
742
+ hideLabel: true,
743
+ density: "compact",
744
+ checked: channel.enabled,
745
+ disabled: channel.disabled,
746
+ onChange: (event) => onToggle?.(category.id, channel.id, event.currentTarget.checked)
747
+ }
748
+ )
749
+ ]
750
+ }
751
+ );
752
+ }
753
+ function safeId(value) {
754
+ return value.replace(/[^a-zA-Z0-9_-]+/g, "-") || "channel";
755
+ }
756
+
757
+ // src/components/MentionList.tsx
758
+ var import_core9 = require("@echothink-ui/core");
759
+ var import_jsx_runtime10 = require("react/jsx-runtime");
760
+ function MentionList({
761
+ mentions,
762
+ onOpen,
763
+ title,
764
+ subtitle,
765
+ className,
766
+ ...props
767
+ }) {
768
+ const hasMentions = mentions.length > 0;
769
+ const countLabel = hasMentions ? `${mentions.length} pending ${mentions.length === 1 ? "reference" : "references"}` : "No pending references";
770
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
771
+ import_core9.Surface,
772
+ {
773
+ ...props,
774
+ title: title ?? "Mentions",
775
+ subtitle: subtitle ?? countLabel,
776
+ className: ["eth-activity-mention-list", className].filter(Boolean).join(" "),
777
+ "data-eth-component": "MentionList",
778
+ children: hasMentions ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("ul", { className: "eth-activity-mention-list__items", "aria-label": "Mention assignments", children: mentions.map((mention) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("li", { className: "eth-activity-mention-list__item", children: [
779
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "eth-activity-mention-list__avatar", "aria-hidden": "true", children: initialsForName(mention.from) }),
780
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "eth-activity-mention-list__content", children: [
781
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "eth-activity-mention-list__header", children: [
782
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { className: "eth-activity-mention-list__sender", children: mention.from }),
783
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "eth-activity-mention-list__reference", children: mention.messageRef })
784
+ ] }),
785
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "eth-activity-mention-list__excerpt", children: mention.excerpt }),
786
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
787
+ "time",
788
+ {
789
+ className: "eth-activity-mention-list__time",
790
+ dateTime: dateTimeValue5(mention.createdAt),
791
+ children: mention.createdAt
792
+ }
793
+ )
794
+ ] }),
795
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
796
+ import_core9.Button,
797
+ {
798
+ type: "button",
799
+ intent: "tertiary",
800
+ density: "compact",
801
+ disabled: !onOpen,
802
+ "aria-label": `Open mention ${mention.messageRef}`,
803
+ onClick: () => onOpen?.(mention.messageRef),
804
+ children: "Open"
805
+ }
806
+ )
807
+ ] }, mention.id)) }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "eth-activity-mention-list__empty", role: "status", children: "No mentions assigned to you." })
808
+ }
809
+ );
810
+ }
811
+ function initialsForName(value) {
812
+ const parts = value.trim().split(/\s+/).filter(Boolean);
813
+ if (parts.length === 0) return "?";
814
+ if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
815
+ return `${parts[0][0]}${parts[parts.length - 1][0]}`.toUpperCase();
816
+ }
817
+ function dateTimeValue5(value) {
818
+ const trimmed = value.trim();
819
+ if (/^\d{2}:\d{2}(:\d{2})?$/.test(trimmed)) return trimmed;
820
+ const date = new Date(trimmed);
821
+ return Number.isFinite(date.valueOf()) ? date.toISOString() : void 0;
822
+ }
823
+
824
+ // src/components/WatcherList.tsx
825
+ var import_core10 = require("@echothink-ui/core");
826
+ var import_icons = require("@echothink-ui/icons");
827
+ var import_jsx_runtime11 = require("react/jsx-runtime");
828
+ function WatcherList({
829
+ watchers,
830
+ onAdd,
831
+ onRemove,
832
+ title,
833
+ subtitle,
834
+ className,
835
+ role,
836
+ footer,
837
+ "aria-label": ariaLabel,
838
+ ...props
839
+ }) {
840
+ const heading = title ?? "Watchers";
841
+ const regionLabel = ariaLabel ?? (typeof heading === "string" ? heading : "Watchers");
842
+ const addAction = onAdd ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
843
+ import_core10.Button,
844
+ {
845
+ type: "button",
846
+ density: "compact",
847
+ intent: "tertiary",
848
+ icon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons.PlusIcon, { size: 16 }),
849
+ onClick: onAdd,
850
+ children: "Add watcher"
851
+ }
852
+ ) : null;
853
+ const surfaceFooter = addAction || footer ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "eth-activity-watcher-list__footer", children: [
854
+ addAction,
855
+ footer
856
+ ] }) : void 0;
857
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
858
+ import_core10.Surface,
859
+ {
860
+ ...props,
861
+ title: heading,
862
+ subtitle: subtitle ?? watcherSummary(watchers.length),
863
+ className: ["eth-activity-watcher-list", className].filter(Boolean).join(" "),
864
+ "data-eth-component": "WatcherList",
865
+ role: role ?? "region",
866
+ "aria-label": regionLabel,
867
+ footer: surfaceFooter,
868
+ children: watchers.length ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("ul", { className: "eth-activity-watcher-list__items", "aria-label": "Watchers", children: watchers.map((watcher) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("li", { className: "eth-activity-watcher-list__item", children: [
869
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "eth-activity-watcher-list__avatar", "aria-hidden": "true", children: watcher.avatar ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("img", { src: watcher.avatar, alt: "" }) : initialsForName2(watcher.label) }),
870
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "eth-activity-watcher-list__identity", children: [
871
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("strong", { children: watcher.label }),
872
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: watcherDetail(watcher) })
873
+ ] }),
874
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "eth-activity-watcher-list__actions", children: [
875
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_core10.Badge, { severity: "neutral", children: watcherKindLabel(watcher.kind) }),
876
+ onRemove ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
877
+ import_core10.IconButton,
878
+ {
879
+ type: "button",
880
+ density: "compact",
881
+ intent: "ghost",
882
+ label: `Remove ${watcher.label} from watchers`,
883
+ icon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons.CloseIcon, { size: 16 }),
884
+ onClick: () => onRemove(watcher.id)
885
+ }
886
+ ) : null
887
+ ] })
888
+ ] }, watcher.id)) }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "eth-activity-watcher-list__empty", role: "status", children: "No watchers have been added." })
889
+ }
890
+ );
891
+ }
892
+ function watcherSummary(count) {
893
+ if (count === 0) return "No watchers configured";
894
+ return `${count} ${count === 1 ? "watcher" : "watchers"} notified on updates`;
895
+ }
896
+ function watcherDetail(watcher) {
897
+ const details = [watcher.role, watcher.email].filter(Boolean);
898
+ return details.length ? details.join(" / ") : "Receives activity updates";
899
+ }
900
+ function watcherKindLabel(kind) {
901
+ if (kind === "group") return "Group";
902
+ if (kind === "service-account") return "Service account";
903
+ return "User";
904
+ }
905
+ function initialsForName2(value) {
906
+ const parts = value.trim().split(/\s+/).filter(Boolean);
907
+ if (!parts.length) return "?";
908
+ if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
909
+ return `${parts[0][0]}${parts[parts.length - 1][0]}`.toUpperCase();
910
+ }
911
+
912
+ // src/index.tsx
913
+ var import_data = require("@echothink-ui/data");
914
+ var ActivityComponentNames = [
915
+ "NotificationCenter",
916
+ "NotificationItem",
917
+ "ActivityFeed",
918
+ "ActivityTimeline",
919
+ "AlertBanner",
920
+ "SystemStatusBanner",
921
+ "IncidentPanel",
922
+ "ChangelogPanel",
923
+ "SubscriptionPreferences",
924
+ "MentionList",
925
+ "WatcherList",
926
+ "AuditLogTable"
927
+ ];
928
+ // Annotate the CommonJS export names for ESM import in node:
929
+ 0 && (module.exports = {
930
+ ActivityComponentNames,
931
+ ActivityFeed,
932
+ ActivityTimeline,
933
+ AlertBanner,
934
+ AuditLogTable,
935
+ ChangelogPanel,
936
+ IncidentPanel,
937
+ MentionList,
938
+ NotificationCenter,
939
+ NotificationItem,
940
+ SubscriptionPreferences,
941
+ SystemStatusBanner,
942
+ WatcherList
943
+ });
944
+ //# sourceMappingURL=index.cjs.map