@buoy-gg/shared-ui 1.7.7 → 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/lib/commonjs/JsModal.js +33 -8
- package/lib/commonjs/clipboard/clipboard-impl.js +1 -1
- package/lib/commonjs/clipboard/copyToClipboard.js +0 -2
- package/lib/commonjs/dataViewer/diffThemes.js +35 -32
- package/lib/commonjs/history/HistoryProvider.js +246 -0
- package/lib/commonjs/history/components/HistoryEntryRow.js +146 -0
- package/lib/commonjs/history/components/HistoryList.js +174 -0
- package/lib/commonjs/history/components/index.js +25 -0
- package/lib/commonjs/history/index.js +61 -0
- package/lib/commonjs/history/types.js +5 -0
- package/lib/commonjs/hooks/safe-area-impl.js +1 -1
- package/lib/commonjs/hooks/useSafeAreaInsets.js +1 -22
- package/lib/commonjs/index.js +37 -46
- package/lib/commonjs/license/FeatureGate.js +13 -42
- package/lib/commonjs/license/index.js +43 -1
- package/lib/commonjs/settings/components/BubbleSettingsSection.js +7 -7
- package/lib/commonjs/storage/devToolsStorageKeys.js +11 -0
- package/lib/commonjs/ui/components/CopyButton.js +14 -29
- package/lib/commonjs/ui/components/DevToolsCard.js +106 -0
- package/lib/commonjs/ui/components/EventHistoryViewer/EventHistoryViewer.js +2 -1
- package/lib/commonjs/ui/components/ExpandablePopover.js +13 -13
- package/lib/commonjs/ui/components/index.js +13 -0
- package/lib/commonjs/utils/formatting/httpFormatting.js +0 -6
- package/lib/commonjs/utils/index.js +0 -31
- package/lib/module/JsModal.js +33 -8
- package/lib/module/clipboard/clipboard-impl.js +1 -1
- package/lib/module/clipboard/copyToClipboard.js +0 -2
- package/lib/module/dataViewer/diffThemes.js +35 -32
- package/lib/module/history/HistoryProvider.js +237 -0
- package/lib/module/history/components/HistoryEntryRow.js +142 -0
- package/lib/module/history/components/HistoryList.js +169 -0
- package/lib/module/history/components/index.js +8 -0
- package/lib/module/history/index.js +15 -0
- package/lib/module/history/types.js +3 -0
- package/lib/module/hooks/safe-area-impl.js +1 -1
- package/lib/module/hooks/useSafeAreaInsets.js +0 -20
- package/lib/module/index.js +5 -4
- package/lib/module/license/FeatureGate.js +11 -40
- package/lib/module/license/index.js +41 -1
- package/lib/module/settings/components/BubbleSettingsSection.js +7 -7
- package/lib/module/storage/devToolsStorageKeys.js +11 -0
- package/lib/module/ui/components/CopyButton.js +12 -28
- package/lib/module/ui/components/DevToolsCard.js +102 -0
- package/lib/module/ui/components/EventHistoryViewer/EventHistoryViewer.js +2 -1
- package/lib/module/ui/components/ExpandablePopover.js +14 -14
- package/lib/module/ui/components/index.js +1 -0
- package/lib/module/utils/formatting/httpFormatting.js +0 -6
- package/lib/module/utils/index.js +0 -1
- package/lib/typescript/commonjs/JsModal.d.ts +2 -0
- package/lib/typescript/commonjs/JsModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/clipboard/clipboard-impl.d.ts +1 -1
- package/lib/typescript/commonjs/clipboard/copyToClipboard.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/diffThemes.d.ts +1 -1
- package/lib/typescript/commonjs/dataViewer/diffThemes.d.ts.map +1 -1
- package/lib/typescript/commonjs/history/HistoryProvider.d.ts +56 -0
- package/lib/typescript/commonjs/history/HistoryProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/history/components/HistoryEntryRow.d.ts +22 -0
- package/lib/typescript/commonjs/history/components/HistoryEntryRow.d.ts.map +1 -0
- package/lib/typescript/commonjs/history/components/HistoryList.d.ts +47 -0
- package/lib/typescript/commonjs/history/components/HistoryList.d.ts.map +1 -0
- package/lib/typescript/commonjs/history/components/index.d.ts +6 -0
- package/lib/typescript/commonjs/history/components/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/history/index.d.ts +9 -0
- package/lib/typescript/commonjs/history/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/history/types.d.ts +171 -0
- package/lib/typescript/commonjs/history/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/commonjs/hooks/useSafeAreaInsets.d.ts +0 -13
- package/lib/typescript/commonjs/hooks/useSafeAreaInsets.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +3 -2
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/license/FeatureGate.d.ts.map +1 -1
- package/lib/typescript/commonjs/license/LicenseEntryModal.d.ts +5 -0
- package/lib/typescript/commonjs/license/LicenseEntryModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/license/index.d.ts +15 -0
- package/lib/typescript/commonjs/license/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts +11 -0
- package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/CopyButton.d.ts +0 -2
- package/lib/typescript/commonjs/ui/components/CopyButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/DevToolsCard.d.ts +54 -0
- package/lib/typescript/commonjs/ui/components/DevToolsCard.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/EventHistoryViewer/EventHistoryViewer.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/index.d.ts +2 -0
- package/lib/typescript/commonjs/ui/components/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/formatting/httpFormatting.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/index.d.ts +0 -1
- package/lib/typescript/commonjs/utils/index.d.ts.map +1 -1
- package/lib/typescript/module/JsModal.d.ts +2 -0
- package/lib/typescript/module/JsModal.d.ts.map +1 -1
- package/lib/typescript/module/clipboard/clipboard-impl.d.ts +1 -1
- package/lib/typescript/module/clipboard/copyToClipboard.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/diffThemes.d.ts +1 -1
- package/lib/typescript/module/dataViewer/diffThemes.d.ts.map +1 -1
- package/lib/typescript/module/history/HistoryProvider.d.ts +56 -0
- package/lib/typescript/module/history/HistoryProvider.d.ts.map +1 -0
- package/lib/typescript/module/history/components/HistoryEntryRow.d.ts +22 -0
- package/lib/typescript/module/history/components/HistoryEntryRow.d.ts.map +1 -0
- package/lib/typescript/module/history/components/HistoryList.d.ts +47 -0
- package/lib/typescript/module/history/components/HistoryList.d.ts.map +1 -0
- package/lib/typescript/module/history/components/index.d.ts +6 -0
- package/lib/typescript/module/history/components/index.d.ts.map +1 -0
- package/lib/typescript/module/history/index.d.ts +9 -0
- package/lib/typescript/module/history/index.d.ts.map +1 -0
- package/lib/typescript/module/history/types.d.ts +171 -0
- package/lib/typescript/module/history/types.d.ts.map +1 -0
- package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/module/hooks/useSafeAreaInsets.d.ts +0 -13
- package/lib/typescript/module/hooks/useSafeAreaInsets.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +3 -2
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/license/FeatureGate.d.ts.map +1 -1
- package/lib/typescript/module/license/LicenseEntryModal.d.ts +5 -0
- package/lib/typescript/module/license/LicenseEntryModal.d.ts.map +1 -1
- package/lib/typescript/module/license/index.d.ts +15 -0
- package/lib/typescript/module/license/index.d.ts.map +1 -1
- package/lib/typescript/module/storage/devToolsStorageKeys.d.ts +11 -0
- package/lib/typescript/module/storage/devToolsStorageKeys.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/CopyButton.d.ts +0 -2
- package/lib/typescript/module/ui/components/CopyButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/DevToolsCard.d.ts +54 -0
- package/lib/typescript/module/ui/components/DevToolsCard.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/EventHistoryViewer/EventHistoryViewer.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/index.d.ts +2 -0
- package/lib/typescript/module/ui/components/index.d.ts.map +1 -1
- package/lib/typescript/module/utils/formatting/httpFormatting.d.ts.map +1 -1
- package/lib/typescript/module/utils/index.d.ts +0 -1
- package/lib/typescript/module/utils/index.d.ts.map +1 -1
- package/package.json +31 -7
- package/scripts/detect-clipboard.js +63 -1
- package/scripts/detect-safe-area.js +63 -1
- package/lib/commonjs/utils/safeAsyncStorage.js +0 -71
- package/lib/module/utils/safeAsyncStorage.js +0 -64
- package/lib/typescript/commonjs/utils/safeAsyncStorage.d.ts +0 -35
- package/lib/typescript/commonjs/utils/safeAsyncStorage.d.ts.map +0 -1
- package/lib/typescript/module/utils/safeAsyncStorage.d.ts +0 -35
- package/lib/typescript/module/utils/safeAsyncStorage.d.ts.map +0 -1
package/lib/commonjs/JsModal.js
CHANGED
|
@@ -9,7 +9,7 @@ var _reactNative = require("react-native");
|
|
|
9
9
|
var _useSafeAreaInsets = require("./hooks/useSafeAreaInsets.js");
|
|
10
10
|
var _index = require("./ui/gameUI/index.js");
|
|
11
11
|
var _index2 = require("./ui/components/index.js");
|
|
12
|
-
var
|
|
12
|
+
var _persistentStorage = require("./utils/persistentStorage.js");
|
|
13
13
|
var _devToolsStorageKeys = require("./storage/devToolsStorageKeys.js");
|
|
14
14
|
var _index3 = require("./context/index.js");
|
|
15
15
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
@@ -58,7 +58,7 @@ class ModalStorage {
|
|
|
58
58
|
static async save(key, value) {
|
|
59
59
|
try {
|
|
60
60
|
this.memoryCache[key] = value;
|
|
61
|
-
await
|
|
61
|
+
await _persistentStorage.persistentStorage.setItem(key, JSON.stringify(value));
|
|
62
62
|
} catch (error) {
|
|
63
63
|
// Failed to save modal state
|
|
64
64
|
}
|
|
@@ -78,7 +78,7 @@ class ModalStorage {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// Load from storage (AsyncStorage or memory fallback)
|
|
81
|
-
const stored = await
|
|
81
|
+
const stored = await _persistentStorage.persistentStorage.getItem(key);
|
|
82
82
|
if (stored) {
|
|
83
83
|
const parsed = JSON.parse(stored);
|
|
84
84
|
this.memoryCache[key] = parsed;
|
|
@@ -339,7 +339,8 @@ const JsModalComponent = ({
|
|
|
339
339
|
onMinimize,
|
|
340
340
|
minimizeTargetPosition,
|
|
341
341
|
initialModalState,
|
|
342
|
-
zIndex
|
|
342
|
+
zIndex,
|
|
343
|
+
disableScrollWrapper = false
|
|
343
344
|
}) => {
|
|
344
345
|
const insets = (0, _useSafeAreaInsets.useSafeAreaInsets)();
|
|
345
346
|
const [isStateLoaded, setIsStateLoaded] = (0, _react.useState)(!enablePersistence);
|
|
@@ -429,7 +430,7 @@ const JsModalComponent = ({
|
|
|
429
430
|
const loadHintStatus = async () => {
|
|
430
431
|
try {
|
|
431
432
|
const hintKey = _devToolsStorageKeys.devToolsStorageKeys.modal.hintAcknowledged();
|
|
432
|
-
const acknowledged = await
|
|
433
|
+
const acknowledged = await _persistentStorage.persistentStorage.getItem(hintKey);
|
|
433
434
|
if (mounted) {
|
|
434
435
|
// Show hint if not acknowledged yet
|
|
435
436
|
setShowHint(acknowledged !== "true");
|
|
@@ -453,7 +454,7 @@ const JsModalComponent = ({
|
|
|
453
454
|
const handleHintAcknowledge = (0, _react.useCallback)(async () => {
|
|
454
455
|
try {
|
|
455
456
|
const hintKey = _devToolsStorageKeys.devToolsStorageKeys.modal.hintAcknowledged();
|
|
456
|
-
await
|
|
457
|
+
await _persistentStorage.persistentStorage.setItem(hintKey, "true");
|
|
457
458
|
setShowHint(false);
|
|
458
459
|
} catch (error) {
|
|
459
460
|
// Failed to save hint acknowledgment, just hide it locally
|
|
@@ -1101,7 +1102,19 @@ const JsModalComponent = ({
|
|
|
1101
1102
|
})
|
|
1102
1103
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1103
1104
|
style: [styles.content, customStyles.content],
|
|
1104
|
-
children: [
|
|
1105
|
+
children: [disableScrollWrapper ?
|
|
1106
|
+
/*#__PURE__*/
|
|
1107
|
+
// Render children directly when they manage their own scrolling (FlatList, etc.)
|
|
1108
|
+
(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
1109
|
+
style: {
|
|
1110
|
+
flex: 1,
|
|
1111
|
+
paddingBottom: footerHeight
|
|
1112
|
+
},
|
|
1113
|
+
children: children
|
|
1114
|
+
}) :
|
|
1115
|
+
/*#__PURE__*/
|
|
1116
|
+
// Wrap in ScrollView for content that needs scrolling
|
|
1117
|
+
(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
|
|
1105
1118
|
style: {
|
|
1106
1119
|
flex: 1
|
|
1107
1120
|
},
|
|
@@ -1190,7 +1203,19 @@ const JsModalComponent = ({
|
|
|
1190
1203
|
onAcknowledge: handleHintAcknowledge
|
|
1191
1204
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1192
1205
|
style: [styles.content, customStyles.content],
|
|
1193
|
-
children: [
|
|
1206
|
+
children: [disableScrollWrapper ?
|
|
1207
|
+
/*#__PURE__*/
|
|
1208
|
+
// Render children directly when they manage their own scrolling (FlatList, etc.)
|
|
1209
|
+
(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
1210
|
+
style: {
|
|
1211
|
+
flex: 1,
|
|
1212
|
+
paddingBottom: footerHeight
|
|
1213
|
+
},
|
|
1214
|
+
children: children
|
|
1215
|
+
}) :
|
|
1216
|
+
/*#__PURE__*/
|
|
1217
|
+
// Wrap in ScrollView for content that needs scrolling
|
|
1218
|
+
(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
|
|
1194
1219
|
style: {
|
|
1195
1220
|
flex: 1
|
|
1196
1221
|
},
|
|
@@ -7,7 +7,7 @@ exports.isClipboardAvailable = exports.clipboardType = exports.clipboardFunction
|
|
|
7
7
|
/**
|
|
8
8
|
* Auto-generated clipboard implementation
|
|
9
9
|
* Detected: none
|
|
10
|
-
* Generated at: 2026-01-
|
|
10
|
+
* Generated at: 2026-01-12T04:02:16.197Z
|
|
11
11
|
*
|
|
12
12
|
* DO NOT EDIT - This file is generated by scripts/detect-clipboard.js
|
|
13
13
|
*
|
|
@@ -26,9 +26,7 @@ async function copyToClipboard(value) {
|
|
|
26
26
|
// This is important when used with virtualized lists or React state
|
|
27
27
|
try {
|
|
28
28
|
// For simple objects, use structured clone if available
|
|
29
|
-
// @ts-expect-error structuredClone is not defined in the browser
|
|
30
29
|
if (typeof structuredClone === "function") {
|
|
31
|
-
// @ts-expect-error tructuredClone is not defined in the browser
|
|
32
30
|
const cloned = structuredClone(value);
|
|
33
31
|
return (0, _safeStringify.safeStringify)(cloned, 2, {
|
|
34
32
|
depthLimit: 100,
|
|
@@ -52,51 +52,54 @@ const gitClassicTheme = exports.gitClassicTheme = {
|
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
* Dev Tools Default Theme
|
|
55
|
-
* Clean dark theme
|
|
55
|
+
* Clean dark theme matching Buoy website brand colors
|
|
56
56
|
*/
|
|
57
57
|
const devToolsDefaultTheme = exports.devToolsDefaultTheme = {
|
|
58
58
|
name: "Dev Tools Default",
|
|
59
|
-
description: "Clean dark theme with
|
|
60
|
-
//
|
|
61
|
-
background: "#
|
|
62
|
-
panelBackground: "#
|
|
63
|
-
headerBackground: "#
|
|
64
|
-
// Diff colors
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
59
|
+
description: "Clean dark theme with Buoy brand colors",
|
|
60
|
+
// Surface colors (matching website dark theme)
|
|
61
|
+
background: "#121212",
|
|
62
|
+
panelBackground: "#1A1A1A",
|
|
63
|
+
headerBackground: "#1A1A1A",
|
|
64
|
+
// Diff colors using website's semantic colors
|
|
65
|
+
// Added: Primary teal (#20C997)
|
|
66
|
+
// Removed: Error red (#EF4444)
|
|
67
|
+
// Modified: Secondary purple (#9B70E0)
|
|
68
|
+
addedBackground: "rgba(32, 201, 151, 0.12)",
|
|
69
|
+
removedBackground: "rgba(239, 68, 68, 0.12)",
|
|
70
|
+
modifiedBackground: "rgba(155, 112, 224, 0.12)",
|
|
68
71
|
unchangedBackground: "transparent",
|
|
69
72
|
contextBackground: "rgba(255, 255, 255, 0.02)",
|
|
70
73
|
// Text colors
|
|
71
|
-
addedText: "#
|
|
72
|
-
removedText: "#
|
|
73
|
-
modifiedText: "#
|
|
74
|
-
unchangedText: "#
|
|
74
|
+
addedText: "#20C997",
|
|
75
|
+
removedText: "#EF4444",
|
|
76
|
+
modifiedText: "#9B70E0",
|
|
77
|
+
unchangedText: "#E0E0E0",
|
|
75
78
|
// Word-level highlights
|
|
76
|
-
addedWordHighlight: "rgba(
|
|
77
|
-
removedWordHighlight: "rgba(
|
|
79
|
+
addedWordHighlight: "rgba(32, 201, 151, 0.3)",
|
|
80
|
+
removedWordHighlight: "rgba(239, 68, 68, 0.3)",
|
|
78
81
|
// UI elements
|
|
79
|
-
lineNumberBackground: "#
|
|
80
|
-
lineNumberText: "#
|
|
81
|
-
lineNumberBorder: "#
|
|
82
|
+
lineNumberBackground: "#121212",
|
|
83
|
+
lineNumberText: "#A0A0A0",
|
|
84
|
+
lineNumberBorder: "#333333",
|
|
82
85
|
// Markers
|
|
83
|
-
markerAddedBackground: "rgba(
|
|
84
|
-
markerRemovedBackground: "rgba(
|
|
85
|
-
markerModifiedBackground: "rgba(
|
|
86
|
-
markerText: "#
|
|
86
|
+
markerAddedBackground: "rgba(32, 201, 151, 0.2)",
|
|
87
|
+
markerRemovedBackground: "rgba(239, 68, 68, 0.2)",
|
|
88
|
+
markerModifiedBackground: "rgba(155, 112, 224, 0.2)",
|
|
89
|
+
markerText: "#A0A0A0",
|
|
87
90
|
// Borders and dividers
|
|
88
|
-
borderColor: "#
|
|
89
|
-
dividerColor: "#
|
|
91
|
+
borderColor: "#333333",
|
|
92
|
+
dividerColor: "#333333",
|
|
90
93
|
// Summary bar
|
|
91
|
-
summaryBackground: "#
|
|
92
|
-
summaryAddedText: "#
|
|
93
|
-
summaryRemovedText: "#
|
|
94
|
-
summaryModifiedText: "#
|
|
94
|
+
summaryBackground: "#1A1A1A",
|
|
95
|
+
summaryAddedText: "#20C997",
|
|
96
|
+
summaryRemovedText: "#EF4444",
|
|
97
|
+
summaryModifiedText: "#9B70E0",
|
|
95
98
|
// Empty state
|
|
96
|
-
emptyStateText: "#
|
|
99
|
+
emptyStateText: "#888888",
|
|
97
100
|
// Separator
|
|
98
|
-
separatorBackground: "#
|
|
99
|
-
separatorText: "#
|
|
101
|
+
separatorBackground: "#1A1A1A",
|
|
102
|
+
separatorText: "#A0A0A0"
|
|
100
103
|
};
|
|
101
104
|
|
|
102
105
|
/**
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.HistoryProvider = HistoryProvider;
|
|
7
|
+
exports.useAllHistoryEntries = useAllHistoryEntries;
|
|
8
|
+
exports.useHistoryAdapter = useHistoryAdapter;
|
|
9
|
+
exports.useHistoryAdapters = useHistoryAdapters;
|
|
10
|
+
exports.useHistoryContext = useHistoryContext;
|
|
11
|
+
exports.useHistoryEntryCounts = useHistoryEntryCounts;
|
|
12
|
+
var _react = require("react");
|
|
13
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
14
|
+
/**
|
|
15
|
+
* HistoryProvider - Context for Universal History DevTools
|
|
16
|
+
*
|
|
17
|
+
* Manages registered adapters and provides unified access to history
|
|
18
|
+
* from Redux, Zustand, MMKV, React Query, etc.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
// =============================================================================
|
|
22
|
+
// CONTEXT VALUE
|
|
23
|
+
// =============================================================================
|
|
24
|
+
|
|
25
|
+
const HistoryContext = /*#__PURE__*/(0, _react.createContext)(null);
|
|
26
|
+
|
|
27
|
+
// =============================================================================
|
|
28
|
+
// PROVIDER
|
|
29
|
+
// =============================================================================
|
|
30
|
+
|
|
31
|
+
function HistoryProvider({
|
|
32
|
+
children,
|
|
33
|
+
initialAdapters = []
|
|
34
|
+
}) {
|
|
35
|
+
// Adapter registry
|
|
36
|
+
const [adapterMap, setAdapterMap] = (0, _react.useState)(() => {
|
|
37
|
+
const map = new Map();
|
|
38
|
+
initialAdapters.forEach(reg => {
|
|
39
|
+
map.set(reg.adapter.id, {
|
|
40
|
+
...reg,
|
|
41
|
+
enabled: reg.enabled ?? true
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
return map;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Selected adapter filter
|
|
48
|
+
const [selectedAdapterId, setSelectedAdapterId] = (0, _react.useState)(null);
|
|
49
|
+
|
|
50
|
+
// Refresh trigger
|
|
51
|
+
const [refreshKey, setRefreshKey] = (0, _react.useState)(0);
|
|
52
|
+
const refresh = (0, _react.useCallback)(() => setRefreshKey(k => k + 1), []);
|
|
53
|
+
|
|
54
|
+
// Subscribe to all adapters
|
|
55
|
+
(0, _react.useEffect)(() => {
|
|
56
|
+
const unsubscribes = [];
|
|
57
|
+
adapterMap.forEach(reg => {
|
|
58
|
+
if (reg.enabled) {
|
|
59
|
+
const unsub = reg.adapter.subscribe(refresh);
|
|
60
|
+
unsubscribes.push(unsub);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return () => {
|
|
64
|
+
unsubscribes.forEach(unsub => unsub());
|
|
65
|
+
};
|
|
66
|
+
}, [adapterMap, refresh]);
|
|
67
|
+
|
|
68
|
+
// Get sorted adapters list
|
|
69
|
+
const adapters = (0, _react.useMemo)(() => {
|
|
70
|
+
return Array.from(adapterMap.values()).filter(reg => reg.enabled).sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100)).map(reg => reg.adapter);
|
|
71
|
+
}, [adapterMap, refreshKey]);
|
|
72
|
+
|
|
73
|
+
// Get adapter by id
|
|
74
|
+
const getAdapter = (0, _react.useCallback)(id => adapterMap.get(id)?.adapter, [adapterMap]);
|
|
75
|
+
|
|
76
|
+
// Register adapter
|
|
77
|
+
const registerAdapter = (0, _react.useCallback)(registration => {
|
|
78
|
+
setAdapterMap(prev => {
|
|
79
|
+
const next = new Map(prev);
|
|
80
|
+
next.set(registration.adapter.id, {
|
|
81
|
+
...registration,
|
|
82
|
+
enabled: registration.enabled ?? true
|
|
83
|
+
});
|
|
84
|
+
return next;
|
|
85
|
+
});
|
|
86
|
+
}, []);
|
|
87
|
+
|
|
88
|
+
// Unregister adapter
|
|
89
|
+
const unregisterAdapter = (0, _react.useCallback)(id => {
|
|
90
|
+
setAdapterMap(prev => {
|
|
91
|
+
const next = new Map(prev);
|
|
92
|
+
next.delete(id);
|
|
93
|
+
return next;
|
|
94
|
+
});
|
|
95
|
+
}, []);
|
|
96
|
+
|
|
97
|
+
// Get all entries (combined or filtered)
|
|
98
|
+
const getAllEntries = (0, _react.useCallback)(filter => {
|
|
99
|
+
let entries = [];
|
|
100
|
+
|
|
101
|
+
// Collect from all (or selected) adapters
|
|
102
|
+
const sourceAdapters = selectedAdapterId && filter?.sources === undefined ? adapters.filter(a => a.id === selectedAdapterId) : adapters;
|
|
103
|
+
sourceAdapters.forEach(adapter => {
|
|
104
|
+
// Skip if sources filter excludes this adapter
|
|
105
|
+
if (filter?.sources && !filter.sources.includes(adapter.id)) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
entries = entries.concat(adapter.getEntries());
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Apply filters
|
|
112
|
+
if (filter) {
|
|
113
|
+
entries = applyFilter(entries, filter);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Sort by timestamp (newest first by default)
|
|
117
|
+
entries.sort((a, b) => b.timestamp - a.timestamp);
|
|
118
|
+
return entries;
|
|
119
|
+
}, [adapters, selectedAdapterId, refreshKey]);
|
|
120
|
+
|
|
121
|
+
// Get entry counts per source
|
|
122
|
+
const getEntryCounts = (0, _react.useCallback)(() => {
|
|
123
|
+
const counts = {};
|
|
124
|
+
adapters.forEach(adapter => {
|
|
125
|
+
counts[adapter.id] = adapter.getEntryCount();
|
|
126
|
+
});
|
|
127
|
+
return counts;
|
|
128
|
+
}, [adapters, refreshKey]);
|
|
129
|
+
const value = (0, _react.useMemo)(() => ({
|
|
130
|
+
adapters,
|
|
131
|
+
getAdapter,
|
|
132
|
+
registerAdapter,
|
|
133
|
+
unregisterAdapter,
|
|
134
|
+
getAllEntries,
|
|
135
|
+
getEntryCounts,
|
|
136
|
+
selectedAdapterId,
|
|
137
|
+
setSelectedAdapterId,
|
|
138
|
+
refresh
|
|
139
|
+
}), [adapters, getAdapter, registerAdapter, unregisterAdapter, getAllEntries, getEntryCounts, selectedAdapterId, refresh]);
|
|
140
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(HistoryContext.Provider, {
|
|
141
|
+
value: value,
|
|
142
|
+
children: children
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// =============================================================================
|
|
147
|
+
// HOOKS
|
|
148
|
+
// =============================================================================
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Get the full history context
|
|
152
|
+
*/
|
|
153
|
+
function useHistoryContext() {
|
|
154
|
+
const context = (0, _react.useContext)(HistoryContext);
|
|
155
|
+
if (!context) {
|
|
156
|
+
throw new Error("useHistoryContext must be used within a HistoryProvider");
|
|
157
|
+
}
|
|
158
|
+
return context;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Get all registered adapters
|
|
163
|
+
*/
|
|
164
|
+
function useHistoryAdapters() {
|
|
165
|
+
return useHistoryContext().adapters;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Get a specific adapter by id
|
|
170
|
+
*/
|
|
171
|
+
function useHistoryAdapter(id) {
|
|
172
|
+
return useHistoryContext().getAdapter(id);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Get combined entries from all adapters
|
|
177
|
+
*/
|
|
178
|
+
function useAllHistoryEntries(filter) {
|
|
179
|
+
const {
|
|
180
|
+
getAllEntries
|
|
181
|
+
} = useHistoryContext();
|
|
182
|
+
return getAllEntries(filter);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Get entry counts per source
|
|
187
|
+
*/
|
|
188
|
+
function useHistoryEntryCounts() {
|
|
189
|
+
return useHistoryContext().getEntryCounts();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// =============================================================================
|
|
193
|
+
// FILTER HELPER
|
|
194
|
+
// =============================================================================
|
|
195
|
+
|
|
196
|
+
function applyFilter(entries, filter) {
|
|
197
|
+
return entries.filter(entry => {
|
|
198
|
+
// Search text
|
|
199
|
+
if (filter.searchText) {
|
|
200
|
+
const search = filter.searchText.toLowerCase();
|
|
201
|
+
if (!entry.label.toLowerCase().includes(search)) {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Only with changes
|
|
207
|
+
if (filter.onlyWithChanges && !entry.hasStateChange) {
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Only errors
|
|
212
|
+
if (filter.onlyErrors && entry.status !== "error") {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Time range
|
|
217
|
+
if (filter.afterTimestamp && entry.timestamp < filter.afterTimestamp) {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
if (filter.beforeTimestamp && entry.timestamp > filter.beforeTimestamp) {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Ignored patterns
|
|
225
|
+
if (filter.ignoredPatterns?.length) {
|
|
226
|
+
for (const pattern of filter.ignoredPatterns) {
|
|
227
|
+
if (new RegExp(pattern).test(entry.label)) {
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Included patterns (must match at least one)
|
|
234
|
+
if (filter.includedPatterns?.length) {
|
|
235
|
+
let matched = false;
|
|
236
|
+
for (const pattern of filter.includedPatterns) {
|
|
237
|
+
if (new RegExp(pattern).test(entry.label)) {
|
|
238
|
+
matched = true;
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (!matched) return false;
|
|
243
|
+
}
|
|
244
|
+
return true;
|
|
245
|
+
});
|
|
246
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.HistoryEntryRow = HistoryEntryRow;
|
|
7
|
+
var _reactNative = require("react-native");
|
|
8
|
+
var _CompactRow = require("../../ui/components/CompactRow.js");
|
|
9
|
+
var _gameUIColors = require("../../ui/gameUI/constants/gameUIColors.js");
|
|
10
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
11
|
+
/**
|
|
12
|
+
* HistoryEntryRow - Universal row component for history entries
|
|
13
|
+
*
|
|
14
|
+
* Wraps CompactRow to display entries from any adapter (Redux, Zustand, MMKV, etc.)
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Format timestamp to relative time
|
|
19
|
+
*/
|
|
20
|
+
function formatRelativeTime(timestamp) {
|
|
21
|
+
const now = Date.now();
|
|
22
|
+
const diff = now - timestamp;
|
|
23
|
+
if (diff < 1000) return "just now";
|
|
24
|
+
if (diff < 60000) return `${Math.floor(diff / 1000)}s ago`;
|
|
25
|
+
if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;
|
|
26
|
+
return `${Math.floor(diff / 3600000)}h ago`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get status color based on entry properties
|
|
31
|
+
*/
|
|
32
|
+
function getStatusColor(entry, adapter) {
|
|
33
|
+
// Use adapter color if available
|
|
34
|
+
if (adapter?.color) {
|
|
35
|
+
return adapter.color;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Status-based colors (React Query style)
|
|
39
|
+
if (entry.status === "error") return _gameUIColors.buoyColors.error;
|
|
40
|
+
if (entry.status === "pending") return _gameUIColors.buoyColors.warning;
|
|
41
|
+
if (entry.status === "success") return _gameUIColors.buoyColors.success;
|
|
42
|
+
|
|
43
|
+
// Change-based colors
|
|
44
|
+
if (entry.hasStateChange) return _gameUIColors.buoyColors.success;
|
|
45
|
+
|
|
46
|
+
// Skipped entries
|
|
47
|
+
if (entry.isSkipped) return _gameUIColors.buoyColors.textMuted;
|
|
48
|
+
|
|
49
|
+
// Future entries (after current index)
|
|
50
|
+
if (entry.isInFuture) return _gameUIColors.buoyColors.textMuted + "80";
|
|
51
|
+
|
|
52
|
+
// Source-based fallback colors
|
|
53
|
+
switch (entry.source) {
|
|
54
|
+
case "redux":
|
|
55
|
+
return "#764ABC";
|
|
56
|
+
// Redux purple
|
|
57
|
+
case "zustand":
|
|
58
|
+
return "#443E38";
|
|
59
|
+
// Zustand brown
|
|
60
|
+
case "mmkv":
|
|
61
|
+
return "#4CAF50";
|
|
62
|
+
// Green
|
|
63
|
+
case "async-storage":
|
|
64
|
+
return "#2196F3";
|
|
65
|
+
// Blue
|
|
66
|
+
case "react-query":
|
|
67
|
+
return "#FF4154";
|
|
68
|
+
// React Query red
|
|
69
|
+
case "jotai":
|
|
70
|
+
return "#000000";
|
|
71
|
+
// Black
|
|
72
|
+
case "legend-state":
|
|
73
|
+
return "#7C3AED";
|
|
74
|
+
// Purple
|
|
75
|
+
default:
|
|
76
|
+
return _gameUIColors.buoyColors.textSecondary;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get status label for display
|
|
82
|
+
*/
|
|
83
|
+
function getStatusLabel(entry) {
|
|
84
|
+
if (entry.isSkipped) return "Skipped";
|
|
85
|
+
if (entry.isInFuture) return "Future";
|
|
86
|
+
if (entry.status) {
|
|
87
|
+
return entry.status.charAt(0).toUpperCase() + entry.status.slice(1);
|
|
88
|
+
}
|
|
89
|
+
if (entry.hasStateChange) return "Changed";
|
|
90
|
+
return "Action";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get sublabel (source or category)
|
|
95
|
+
*/
|
|
96
|
+
function getSublabel(entry, adapter) {
|
|
97
|
+
if (adapter?.name) return adapter.name;
|
|
98
|
+
if (entry.category) return entry.category;
|
|
99
|
+
return entry.source;
|
|
100
|
+
}
|
|
101
|
+
function HistoryEntryRow({
|
|
102
|
+
entry,
|
|
103
|
+
adapter,
|
|
104
|
+
isSelected,
|
|
105
|
+
onPress,
|
|
106
|
+
showSource = true,
|
|
107
|
+
showDuration = true
|
|
108
|
+
}) {
|
|
109
|
+
const statusColor = getStatusColor(entry, adapter);
|
|
110
|
+
const statusLabel = getStatusLabel(entry);
|
|
111
|
+
const sublabel = showSource ? getSublabel(entry, adapter) : undefined;
|
|
112
|
+
|
|
113
|
+
// Build bottom right text (timestamp + optional duration)
|
|
114
|
+
let bottomRightText = formatRelativeTime(entry.timestamp);
|
|
115
|
+
if (showDuration && entry.duration !== undefined) {
|
|
116
|
+
bottomRightText = `${entry.duration.toFixed(1)}ms · ${bottomRightText}`;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Custom badge showing change indicator
|
|
120
|
+
const customBadge = entry.hasStateChange ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
121
|
+
style: styles.changeBadge,
|
|
122
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
123
|
+
style: styles.changeBadgeText,
|
|
124
|
+
children: "\u26A1"
|
|
125
|
+
})
|
|
126
|
+
}) : undefined;
|
|
127
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_CompactRow.CompactRow, {
|
|
128
|
+
statusDotColor: statusColor,
|
|
129
|
+
statusLabel: statusLabel,
|
|
130
|
+
statusSublabel: sublabel,
|
|
131
|
+
primaryText: entry.label,
|
|
132
|
+
bottomRightText: bottomRightText,
|
|
133
|
+
customBadge: customBadge,
|
|
134
|
+
isSelected: isSelected,
|
|
135
|
+
onPress: onPress ? () => onPress(entry) : undefined,
|
|
136
|
+
showChevron: !!onPress
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
const styles = _reactNative.StyleSheet.create({
|
|
140
|
+
changeBadge: {
|
|
141
|
+
paddingHorizontal: 4
|
|
142
|
+
},
|
|
143
|
+
changeBadgeText: {
|
|
144
|
+
fontSize: 12
|
|
145
|
+
}
|
|
146
|
+
});
|