@buoy-gg/events 2.1.1
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/LICENSE +58 -0
- package/README.md +55 -0
- package/lib/commonjs/components/EventsCopySettingsView.js +645 -0
- package/lib/commonjs/components/EventsModal.js +263 -0
- package/lib/commonjs/components/ReactQueryEventDetail.js +428 -0
- package/lib/commonjs/components/UnifiedEventDetail.js +370 -0
- package/lib/commonjs/components/UnifiedEventFilters.js +113 -0
- package/lib/commonjs/components/UnifiedEventItem.js +349 -0
- package/lib/commonjs/components/UnifiedEventList.js +154 -0
- package/lib/commonjs/components/UnifiedEventViewer.js +126 -0
- package/lib/commonjs/hooks/useUnifiedEvents.js +237 -0
- package/lib/commonjs/index.js +205 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/preset.js +66 -0
- package/lib/commonjs/stores/unifiedEventStore.js +413 -0
- package/lib/commonjs/types/copySettings.js +220 -0
- package/lib/commonjs/types/index.js +17 -0
- package/lib/commonjs/utils/autoDiscoverEventSources.js +640 -0
- package/lib/commonjs/utils/badgeSelectionStorage.js +58 -0
- package/lib/commonjs/utils/copySettingsStorage.js +66 -0
- package/lib/commonjs/utils/correlationUtils.js +130 -0
- package/lib/commonjs/utils/eventExportFormatter.js +1095 -0
- package/lib/commonjs/utils/eventTransformers.js +496 -0
- package/lib/module/components/EventsCopySettingsView.js +641 -0
- package/lib/module/components/EventsModal.js +259 -0
- package/lib/module/components/ReactQueryEventDetail.js +424 -0
- package/lib/module/components/UnifiedEventDetail.js +366 -0
- package/lib/module/components/UnifiedEventFilters.js +109 -0
- package/lib/module/components/UnifiedEventItem.js +345 -0
- package/lib/module/components/UnifiedEventList.js +150 -0
- package/lib/module/components/UnifiedEventViewer.js +122 -0
- package/lib/module/hooks/useUnifiedEvents.js +234 -0
- package/lib/module/index.js +77 -0
- package/lib/module/preset.js +62 -0
- package/lib/module/stores/unifiedEventStore.js +387 -0
- package/lib/module/types/copySettings.js +215 -0
- package/lib/module/types/index.js +37 -0
- package/lib/module/utils/autoDiscoverEventSources.js +633 -0
- package/lib/module/utils/badgeSelectionStorage.js +52 -0
- package/lib/module/utils/copySettingsStorage.js +61 -0
- package/lib/module/utils/correlationUtils.js +120 -0
- package/lib/module/utils/eventExportFormatter.js +1085 -0
- package/lib/module/utils/eventTransformers.js +487 -0
- package/lib/typescript/components/EventsCopySettingsView.d.ts +16 -0
- package/lib/typescript/components/EventsModal.d.ts +16 -0
- package/lib/typescript/components/ReactQueryEventDetail.d.ts +15 -0
- package/lib/typescript/components/UnifiedEventDetail.d.ts +15 -0
- package/lib/typescript/components/UnifiedEventFilters.d.ts +21 -0
- package/lib/typescript/components/UnifiedEventItem.d.ts +26 -0
- package/lib/typescript/components/UnifiedEventList.d.ts +27 -0
- package/lib/typescript/components/UnifiedEventViewer.d.ts +8 -0
- package/lib/typescript/hooks/useUnifiedEvents.d.ts +30 -0
- package/lib/typescript/index.d.ts +28 -0
- package/lib/typescript/preset.d.ts +62 -0
- package/lib/typescript/stores/unifiedEventStore.d.ts +146 -0
- package/lib/typescript/types/copySettings.d.ts +179 -0
- package/lib/typescript/types/index.d.ts +73 -0
- package/lib/typescript/utils/autoDiscoverEventSources.d.ts +74 -0
- package/lib/typescript/utils/badgeSelectionStorage.d.ts +21 -0
- package/lib/typescript/utils/copySettingsStorage.d.ts +21 -0
- package/lib/typescript/utils/correlationUtils.d.ts +36 -0
- package/lib/typescript/utils/eventExportFormatter.d.ts +49 -0
- package/lib/typescript/utils/eventTransformers.d.ts +119 -0
- package/package.json +91 -0
- package/src/components/EventsCopySettingsView.tsx +742 -0
- package/src/components/EventsModal.tsx +328 -0
- package/src/components/ReactQueryEventDetail.tsx +413 -0
- package/src/components/UnifiedEventDetail.tsx +371 -0
- package/src/components/UnifiedEventFilters.tsx +156 -0
- package/src/components/UnifiedEventItem.tsx +396 -0
- package/src/components/UnifiedEventList.tsx +197 -0
- package/src/components/UnifiedEventViewer.tsx +132 -0
- package/src/hooks/useUnifiedEvents.ts +288 -0
- package/src/index.tsx +112 -0
- package/src/preset.tsx +57 -0
- package/src/stores/unifiedEventStore.ts +405 -0
- package/src/types/copySettings.ts +269 -0
- package/src/types/index.ts +96 -0
- package/src/utils/autoDiscoverEventSources.ts +690 -0
- package/src/utils/badgeSelectionStorage.ts +51 -0
- package/src/utils/copySettingsStorage.ts +61 -0
- package/src/utils/correlationUtils.ts +146 -0
- package/src/utils/eventExportFormatter.ts +1233 -0
- package/src/utils/eventTransformers.ts +567 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* UnifiedEventDetail
|
|
5
|
+
*
|
|
6
|
+
* Detail view for a single unified event.
|
|
7
|
+
* Uses shared detail components from other packages when available,
|
|
8
|
+
* falls back to generic DataViewer when packages aren't installed.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { View, Text, StyleSheet, ScrollView } from "react-native";
|
|
12
|
+
import { memo, useMemo } from "react";
|
|
13
|
+
import { buoyColors, formatRelativeTime, copyToClipboard, parseValue } from "@buoy-gg/shared-ui";
|
|
14
|
+
import { DataViewer } from "@buoy-gg/shared-ui/dataViewer";
|
|
15
|
+
import { ReactQueryEventDetail } from "./ReactQueryEventDetail";
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Optional Component Loading
|
|
19
|
+
// ============================================================================
|
|
20
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
21
|
+
function tryLoadOptionalDetailComponents() {
|
|
22
|
+
const components = {
|
|
23
|
+
StorageEventDetailContent: null,
|
|
24
|
+
ReduxActionDetailContent: null,
|
|
25
|
+
NetworkEventDetailView: null
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Try to load storage detail component
|
|
29
|
+
try {
|
|
30
|
+
// @ts-ignore - Dynamic import that may not exist
|
|
31
|
+
const storage = require("@buoy-gg/storage");
|
|
32
|
+
components.StorageEventDetailContent = storage.StorageEventDetailContent;
|
|
33
|
+
} catch {
|
|
34
|
+
// Optional dependency not installed
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Try to load redux detail component
|
|
38
|
+
try {
|
|
39
|
+
// @ts-ignore - Dynamic import that may not exist
|
|
40
|
+
const redux = require("@buoy-gg/redux");
|
|
41
|
+
components.ReduxActionDetailContent = redux.ReduxActionDetailContent;
|
|
42
|
+
} catch {
|
|
43
|
+
// Optional dependency not installed
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Try to load network detail component
|
|
47
|
+
try {
|
|
48
|
+
// @ts-ignore - Dynamic import that may not exist
|
|
49
|
+
const network = require("@buoy-gg/network");
|
|
50
|
+
components.NetworkEventDetailView = network.NetworkEventDetailView;
|
|
51
|
+
} catch {
|
|
52
|
+
// Optional dependency not installed
|
|
53
|
+
}
|
|
54
|
+
return components;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Cache loaded components
|
|
58
|
+
const optionalComponents = tryLoadOptionalDetailComponents();
|
|
59
|
+
|
|
60
|
+
// ============================================================================
|
|
61
|
+
// Configuration
|
|
62
|
+
// ============================================================================
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Source configuration for display
|
|
66
|
+
*/
|
|
67
|
+
const SOURCE_CONFIG = {
|
|
68
|
+
"storage-async": {
|
|
69
|
+
label: "AsyncStorage",
|
|
70
|
+
color: "#8B5CF6"
|
|
71
|
+
},
|
|
72
|
+
"storage-mmkv": {
|
|
73
|
+
label: "MMKV",
|
|
74
|
+
color: "#F59E0B"
|
|
75
|
+
},
|
|
76
|
+
redux: {
|
|
77
|
+
label: "Redux",
|
|
78
|
+
color: "#3B82F6"
|
|
79
|
+
},
|
|
80
|
+
network: {
|
|
81
|
+
label: "Network",
|
|
82
|
+
color: "#10B981"
|
|
83
|
+
},
|
|
84
|
+
"react-query": {
|
|
85
|
+
label: "React Query",
|
|
86
|
+
color: "#EC4899"
|
|
87
|
+
},
|
|
88
|
+
"react-query-query": {
|
|
89
|
+
label: "Query",
|
|
90
|
+
color: "#EC4899"
|
|
91
|
+
},
|
|
92
|
+
"react-query-mutation": {
|
|
93
|
+
label: "Mutation",
|
|
94
|
+
color: "#F97316"
|
|
95
|
+
},
|
|
96
|
+
route: {
|
|
97
|
+
label: "Route",
|
|
98
|
+
color: "#06B6D4"
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Check if an event is a storage event
|
|
104
|
+
*/
|
|
105
|
+
function isStorageEvent(source) {
|
|
106
|
+
return source === "storage-async" || source === "storage-mmkv";
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Get value type from a value
|
|
111
|
+
*/
|
|
112
|
+
function getValueType(value) {
|
|
113
|
+
const parsed = parseValue(value);
|
|
114
|
+
if (parsed === null) return "null";
|
|
115
|
+
if (parsed === undefined) return "undefined";
|
|
116
|
+
if (Array.isArray(parsed)) return "array";
|
|
117
|
+
if (typeof parsed === "boolean") return "boolean";
|
|
118
|
+
if (typeof parsed === "number") return "number";
|
|
119
|
+
if (typeof parsed === "string") return "string";
|
|
120
|
+
if (typeof parsed === "object") return "object";
|
|
121
|
+
return "undefined";
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ============================================================================
|
|
125
|
+
// Component
|
|
126
|
+
// ============================================================================
|
|
127
|
+
|
|
128
|
+
export const UnifiedEventDetail = /*#__PURE__*/memo(function UnifiedEventDetail({
|
|
129
|
+
event,
|
|
130
|
+
onBack
|
|
131
|
+
}) {
|
|
132
|
+
const sourceConfig = SOURCE_CONFIG[event.source];
|
|
133
|
+
const timestamp = new Date(event.timestamp);
|
|
134
|
+
|
|
135
|
+
// For storage events, create a conversation object to use with StorageEventDetailContent
|
|
136
|
+
const storageConversation = useMemo(() => {
|
|
137
|
+
if (!isStorageEvent(event.source)) return null;
|
|
138
|
+
if (!optionalComponents.StorageEventDetailContent) return null;
|
|
139
|
+
const originalEvent = event.originalEvent;
|
|
140
|
+
|
|
141
|
+
// Create a conversation with a single event for the detail view
|
|
142
|
+
return {
|
|
143
|
+
key: originalEvent.data?.key || "unknown",
|
|
144
|
+
lastEvent: originalEvent,
|
|
145
|
+
events: [originalEvent],
|
|
146
|
+
totalOperations: 1,
|
|
147
|
+
currentValue: originalEvent.data?.value,
|
|
148
|
+
valueType: getValueType(originalEvent.data?.value),
|
|
149
|
+
storageTypes: new Set([originalEvent.storageType || "async"])
|
|
150
|
+
};
|
|
151
|
+
}, [event]);
|
|
152
|
+
|
|
153
|
+
// For storage events, use the shared StorageEventDetailContent if available
|
|
154
|
+
if (storageConversation && optionalComponents.StorageEventDetailContent) {
|
|
155
|
+
const {
|
|
156
|
+
StorageEventDetailContent
|
|
157
|
+
} = optionalComponents;
|
|
158
|
+
return /*#__PURE__*/_jsx(View, {
|
|
159
|
+
style: styles.container,
|
|
160
|
+
children: /*#__PURE__*/_jsx(StorageEventDetailContent, {
|
|
161
|
+
conversation: storageConversation,
|
|
162
|
+
selectedEventIndex: 0,
|
|
163
|
+
onEventIndexChange: () => {},
|
|
164
|
+
disableInternalFooter: true
|
|
165
|
+
})
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// For Redux events, use the shared ReduxActionDetailContent if available
|
|
170
|
+
if (event.source === "redux" && optionalComponents.ReduxActionDetailContent) {
|
|
171
|
+
const {
|
|
172
|
+
ReduxActionDetailContent
|
|
173
|
+
} = optionalComponents;
|
|
174
|
+
const reduxAction = event.originalEvent;
|
|
175
|
+
return /*#__PURE__*/_jsx(View, {
|
|
176
|
+
style: styles.container,
|
|
177
|
+
children: /*#__PURE__*/_jsx(ReduxActionDetailContent, {
|
|
178
|
+
action: reduxAction,
|
|
179
|
+
actions: [reduxAction],
|
|
180
|
+
selectedIndex: 0,
|
|
181
|
+
onIndexChange: () => {},
|
|
182
|
+
disableInternalFooter: true
|
|
183
|
+
})
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// For network events, use the shared NetworkEventDetailView if available
|
|
188
|
+
if (event.source === "network" && optionalComponents.NetworkEventDetailView) {
|
|
189
|
+
const {
|
|
190
|
+
NetworkEventDetailView
|
|
191
|
+
} = optionalComponents;
|
|
192
|
+
const networkEvent = event.originalEvent;
|
|
193
|
+
return /*#__PURE__*/_jsx(View, {
|
|
194
|
+
style: styles.container,
|
|
195
|
+
children: /*#__PURE__*/_jsx(ScrollView, {
|
|
196
|
+
style: styles.content,
|
|
197
|
+
children: /*#__PURE__*/_jsx(NetworkEventDetailView, {
|
|
198
|
+
event: networkEvent
|
|
199
|
+
})
|
|
200
|
+
})
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// For React Query events, use the specialized ReactQueryEventDetail
|
|
205
|
+
if (event.source === "react-query" || event.source === "react-query-query" || event.source === "react-query-mutation") {
|
|
206
|
+
return /*#__PURE__*/_jsx(View, {
|
|
207
|
+
style: styles.container,
|
|
208
|
+
children: /*#__PURE__*/_jsx(ReactQueryEventDetail, {
|
|
209
|
+
event: event
|
|
210
|
+
})
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Route events expand in-place in the list, so they shouldn't reach this detail view
|
|
215
|
+
// If they do somehow, fall through to the generic view
|
|
216
|
+
|
|
217
|
+
// For all other events (or when specific components aren't available), show the generic detail view
|
|
218
|
+
const getEventData = () => {
|
|
219
|
+
return event.originalEvent;
|
|
220
|
+
};
|
|
221
|
+
const handleCopy = async () => {
|
|
222
|
+
await copyToClipboard({
|
|
223
|
+
source: event.source,
|
|
224
|
+
timestamp: timestamp.toISOString(),
|
|
225
|
+
title: event.title,
|
|
226
|
+
subtitle: event.subtitle,
|
|
227
|
+
data: getEventData()
|
|
228
|
+
});
|
|
229
|
+
};
|
|
230
|
+
return /*#__PURE__*/_jsx(View, {
|
|
231
|
+
style: styles.container,
|
|
232
|
+
children: /*#__PURE__*/_jsxs(ScrollView, {
|
|
233
|
+
style: styles.content,
|
|
234
|
+
contentContainerStyle: styles.contentContainer,
|
|
235
|
+
children: [/*#__PURE__*/_jsx(View, {
|
|
236
|
+
style: styles.sourceBadgeRow,
|
|
237
|
+
children: /*#__PURE__*/_jsxs(View, {
|
|
238
|
+
style: [styles.sourceBadge, {
|
|
239
|
+
backgroundColor: sourceConfig.color + "20"
|
|
240
|
+
}],
|
|
241
|
+
children: [/*#__PURE__*/_jsx(View, {
|
|
242
|
+
style: [styles.sourceDot, {
|
|
243
|
+
backgroundColor: sourceConfig.color
|
|
244
|
+
}]
|
|
245
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
246
|
+
style: [styles.sourceLabel, {
|
|
247
|
+
color: sourceConfig.color
|
|
248
|
+
}],
|
|
249
|
+
children: sourceConfig.label
|
|
250
|
+
})]
|
|
251
|
+
})
|
|
252
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
253
|
+
style: styles.title,
|
|
254
|
+
children: event.title
|
|
255
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
256
|
+
style: styles.subtitle,
|
|
257
|
+
children: event.subtitle
|
|
258
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
259
|
+
style: styles.timestampRow,
|
|
260
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
261
|
+
style: styles.timestampLabel,
|
|
262
|
+
children: "Timestamp"
|
|
263
|
+
}), /*#__PURE__*/_jsxs(Text, {
|
|
264
|
+
style: styles.timestampValue,
|
|
265
|
+
children: [timestamp.toLocaleTimeString(), " (", formatRelativeTime(timestamp), ")"]
|
|
266
|
+
})]
|
|
267
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
268
|
+
style: styles.dataSection,
|
|
269
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
270
|
+
style: styles.sectionLabel,
|
|
271
|
+
children: "Event Data"
|
|
272
|
+
}), /*#__PURE__*/_jsx(View, {
|
|
273
|
+
style: styles.dataContainer,
|
|
274
|
+
children: /*#__PURE__*/_jsx(DataViewer, {
|
|
275
|
+
data: getEventData(),
|
|
276
|
+
title: "",
|
|
277
|
+
showTypeFilter: false
|
|
278
|
+
})
|
|
279
|
+
})]
|
|
280
|
+
})]
|
|
281
|
+
})
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
const styles = StyleSheet.create({
|
|
285
|
+
container: {
|
|
286
|
+
flex: 1,
|
|
287
|
+
backgroundColor: buoyColors.base
|
|
288
|
+
},
|
|
289
|
+
content: {
|
|
290
|
+
flex: 1
|
|
291
|
+
},
|
|
292
|
+
contentContainer: {
|
|
293
|
+
padding: 16
|
|
294
|
+
},
|
|
295
|
+
sourceBadgeRow: {
|
|
296
|
+
flexDirection: "row",
|
|
297
|
+
marginBottom: 12
|
|
298
|
+
},
|
|
299
|
+
sourceBadge: {
|
|
300
|
+
flexDirection: "row",
|
|
301
|
+
alignItems: "center",
|
|
302
|
+
paddingHorizontal: 10,
|
|
303
|
+
paddingVertical: 6,
|
|
304
|
+
borderRadius: 12,
|
|
305
|
+
gap: 6
|
|
306
|
+
},
|
|
307
|
+
sourceDot: {
|
|
308
|
+
width: 6,
|
|
309
|
+
height: 6,
|
|
310
|
+
borderRadius: 3
|
|
311
|
+
},
|
|
312
|
+
sourceLabel: {
|
|
313
|
+
fontSize: 12,
|
|
314
|
+
fontWeight: "600"
|
|
315
|
+
},
|
|
316
|
+
title: {
|
|
317
|
+
fontSize: 24,
|
|
318
|
+
fontWeight: "700",
|
|
319
|
+
color: buoyColors.text,
|
|
320
|
+
marginBottom: 4
|
|
321
|
+
},
|
|
322
|
+
subtitle: {
|
|
323
|
+
fontSize: 16,
|
|
324
|
+
color: buoyColors.textMuted,
|
|
325
|
+
marginBottom: 16
|
|
326
|
+
},
|
|
327
|
+
timestampRow: {
|
|
328
|
+
flexDirection: "row",
|
|
329
|
+
justifyContent: "space-between",
|
|
330
|
+
alignItems: "center",
|
|
331
|
+
paddingVertical: 12,
|
|
332
|
+
borderTopWidth: 1,
|
|
333
|
+
borderTopColor: buoyColors.border,
|
|
334
|
+
borderBottomWidth: 1,
|
|
335
|
+
borderBottomColor: buoyColors.border,
|
|
336
|
+
marginBottom: 16
|
|
337
|
+
},
|
|
338
|
+
timestampLabel: {
|
|
339
|
+
fontSize: 14,
|
|
340
|
+
color: buoyColors.textMuted
|
|
341
|
+
},
|
|
342
|
+
timestampValue: {
|
|
343
|
+
fontSize: 14,
|
|
344
|
+
color: buoyColors.text,
|
|
345
|
+
fontFamily: "monospace"
|
|
346
|
+
},
|
|
347
|
+
dataSection: {
|
|
348
|
+
marginTop: 8
|
|
349
|
+
},
|
|
350
|
+
sectionLabel: {
|
|
351
|
+
fontSize: 12,
|
|
352
|
+
fontWeight: "600",
|
|
353
|
+
color: buoyColors.textMuted,
|
|
354
|
+
textTransform: "uppercase",
|
|
355
|
+
letterSpacing: 0.5,
|
|
356
|
+
marginBottom: 8
|
|
357
|
+
},
|
|
358
|
+
dataContainer: {
|
|
359
|
+
backgroundColor: buoyColors.card,
|
|
360
|
+
borderRadius: 8,
|
|
361
|
+
borderWidth: 1,
|
|
362
|
+
borderColor: buoyColors.border,
|
|
363
|
+
overflow: "hidden"
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
//# sourceMappingURL=UnifiedEventDetail.js.map
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* UnifiedEventFilters
|
|
5
|
+
*
|
|
6
|
+
* Filter bar showing toggleable badges for each available event source.
|
|
7
|
+
* Badges are sorted: enabled first, disabled last.
|
|
8
|
+
* Toggling a badge enables/disables event listening for that source.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { View, Text, TouchableOpacity, StyleSheet, ScrollView } from "react-native";
|
|
12
|
+
import { memo } from "react";
|
|
13
|
+
import { buoyColors } from "@buoy-gg/shared-ui";
|
|
14
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
15
|
+
export const UnifiedEventFilters = /*#__PURE__*/memo(function UnifiedEventFilters({
|
|
16
|
+
availableSources,
|
|
17
|
+
onToggleSource,
|
|
18
|
+
totalCount,
|
|
19
|
+
filteredCount
|
|
20
|
+
}) {
|
|
21
|
+
if (availableSources.length === 0) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
25
|
+
style: styles.container,
|
|
26
|
+
children: [/*#__PURE__*/_jsx(ScrollView, {
|
|
27
|
+
horizontal: true,
|
|
28
|
+
showsHorizontalScrollIndicator: false,
|
|
29
|
+
contentContainerStyle: styles.badgesRow,
|
|
30
|
+
children: availableSources.map(source => {
|
|
31
|
+
const isEnabled = source.enabled !== false;
|
|
32
|
+
return /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
33
|
+
style: [styles.badge, isEnabled ? {
|
|
34
|
+
backgroundColor: source.color + "20",
|
|
35
|
+
borderColor: source.color + "60"
|
|
36
|
+
} : styles.badgeDisabled],
|
|
37
|
+
onPress: () => onToggleSource(source.source),
|
|
38
|
+
activeOpacity: 0.7,
|
|
39
|
+
children: [/*#__PURE__*/_jsx(View, {
|
|
40
|
+
style: [styles.dot, {
|
|
41
|
+
backgroundColor: isEnabled ? source.color : buoyColors.textMuted + "60"
|
|
42
|
+
}]
|
|
43
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
44
|
+
style: [styles.badgeLabel, {
|
|
45
|
+
color: isEnabled ? source.color : buoyColors.textMuted + "80"
|
|
46
|
+
}],
|
|
47
|
+
children: source.label
|
|
48
|
+
}), isEnabled && source.count > 0 && /*#__PURE__*/_jsx(Text, {
|
|
49
|
+
style: [styles.badgeCount, {
|
|
50
|
+
color: source.color
|
|
51
|
+
}],
|
|
52
|
+
children: source.count
|
|
53
|
+
})]
|
|
54
|
+
}, source.source);
|
|
55
|
+
})
|
|
56
|
+
}), filteredCount < totalCount && /*#__PURE__*/_jsxs(Text, {
|
|
57
|
+
style: styles.filterInfo,
|
|
58
|
+
children: ["Showing ", filteredCount, " of ", totalCount]
|
|
59
|
+
})]
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
const styles = StyleSheet.create({
|
|
63
|
+
container: {
|
|
64
|
+
paddingVertical: 8,
|
|
65
|
+
backgroundColor: buoyColors.base,
|
|
66
|
+
borderBottomWidth: 1,
|
|
67
|
+
borderBottomColor: buoyColors.border
|
|
68
|
+
},
|
|
69
|
+
badgesRow: {
|
|
70
|
+
flexDirection: "row",
|
|
71
|
+
gap: 8,
|
|
72
|
+
paddingHorizontal: 12
|
|
73
|
+
},
|
|
74
|
+
badge: {
|
|
75
|
+
flexDirection: "row",
|
|
76
|
+
alignItems: "center",
|
|
77
|
+
paddingHorizontal: 10,
|
|
78
|
+
paddingVertical: 6,
|
|
79
|
+
borderRadius: 16,
|
|
80
|
+
borderWidth: 1,
|
|
81
|
+
gap: 6
|
|
82
|
+
},
|
|
83
|
+
badgeDisabled: {
|
|
84
|
+
backgroundColor: buoyColors.card,
|
|
85
|
+
borderColor: buoyColors.border,
|
|
86
|
+
opacity: 0.6
|
|
87
|
+
},
|
|
88
|
+
dot: {
|
|
89
|
+
width: 6,
|
|
90
|
+
height: 6,
|
|
91
|
+
borderRadius: 3
|
|
92
|
+
},
|
|
93
|
+
badgeLabel: {
|
|
94
|
+
fontSize: 12,
|
|
95
|
+
fontWeight: "600"
|
|
96
|
+
},
|
|
97
|
+
badgeCount: {
|
|
98
|
+
fontSize: 11,
|
|
99
|
+
fontWeight: "500",
|
|
100
|
+
opacity: 0.8
|
|
101
|
+
},
|
|
102
|
+
filterInfo: {
|
|
103
|
+
marginTop: 6,
|
|
104
|
+
fontSize: 11,
|
|
105
|
+
color: buoyColors.textMuted,
|
|
106
|
+
textAlign: "center"
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
//# sourceMappingURL=UnifiedEventFilters.js.map
|