@buoy-gg/shared-ui 7.0.33 → 7.0.34
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 +57 -22
- package/lib/commonjs/hooks/index.js +26 -0
- package/lib/commonjs/hooks/safe-area-impl.js +1 -1
- package/lib/commonjs/hooks/useChangeLog.js +55 -0
- package/lib/commonjs/hooks/useEventStoreEvents.js +65 -0
- package/lib/commonjs/hooks/usePersistedState.js +45 -10
- package/lib/commonjs/index.js +143 -0
- package/lib/commonjs/storage/definePersistedSetting.js +67 -0
- package/lib/commonjs/storage/index.js +8 -1
- package/lib/commonjs/stores/ChangeLog.js +197 -0
- package/lib/commonjs/stores/createToolStore.js +175 -0
- package/lib/commonjs/stores/index.js +15 -1
- package/lib/commonjs/sync/toolSyncAdapter.js +63 -0
- package/lib/commonjs/sync/wireForm.js +172 -0
- package/lib/commonjs/tools/defineTool.js +79 -0
- package/lib/commonjs/ui/components/ChangeRow.js +110 -0
- package/lib/commonjs/ui/components/ChipStrip.js +94 -0
- package/lib/commonjs/ui/components/DetailViewToggle.js +130 -0
- package/lib/commonjs/ui/components/DevToolsCard.js +3 -1
- package/lib/commonjs/ui/components/EntityFilterView.js +354 -0
- package/lib/commonjs/ui/components/ExportPreview.js +174 -0
- package/lib/commonjs/ui/components/InfoRow.js +90 -0
- package/lib/commonjs/ui/components/ModalHeader.js +40 -7
- package/lib/commonjs/ui/components/Pill.js +114 -0
- package/lib/commonjs/ui/components/ToggleRow.js +116 -0
- package/lib/commonjs/ui/components/ToolFooter.js +204 -0
- package/lib/commonjs/ui/components/index.js +100 -1
- package/lib/commonjs/ui/index.js +24 -2
- package/lib/commonjs/ui/listPresets.js +43 -0
- package/lib/commonjs/ui/night/primitives.js +3 -1
- package/lib/commonjs/utils/snapshotProviderKit.js +167 -0
- package/lib/commonjs/utils/stateTools.js +160 -0
- package/lib/module/JsModal.js +57 -22
- package/lib/module/hooks/index.js +3 -1
- package/lib/module/hooks/safe-area-impl.js +1 -1
- package/lib/module/hooks/useChangeLog.js +50 -0
- package/lib/module/hooks/useEventStoreEvents.js +61 -0
- package/lib/module/hooks/usePersistedState.js +44 -10
- package/lib/module/index.js +11 -1
- package/lib/module/storage/definePersistedSetting.js +63 -0
- package/lib/module/storage/index.js +2 -1
- package/lib/module/stores/ChangeLog.js +192 -0
- package/lib/module/stores/createToolStore.js +171 -0
- package/lib/module/stores/index.js +3 -1
- package/lib/module/sync/toolSyncAdapter.js +58 -0
- package/lib/module/sync/wireForm.js +159 -0
- package/lib/module/tools/defineTool.js +74 -0
- package/lib/module/ui/components/ChangeRow.js +105 -0
- package/lib/module/ui/components/ChipStrip.js +91 -0
- package/lib/module/ui/components/DetailViewToggle.js +125 -0
- package/lib/module/ui/components/DevToolsCard.js +3 -1
- package/lib/module/ui/components/EntityFilterView.js +350 -0
- package/lib/module/ui/components/ExportPreview.js +169 -0
- package/lib/module/ui/components/InfoRow.js +86 -0
- package/lib/module/ui/components/ModalHeader.js +40 -7
- package/lib/module/ui/components/Pill.js +110 -0
- package/lib/module/ui/components/ToggleRow.js +112 -0
- package/lib/module/ui/components/ToolFooter.js +196 -0
- package/lib/module/ui/components/index.js +10 -1
- package/lib/module/ui/index.js +4 -1
- package/lib/module/ui/listPresets.js +39 -0
- package/lib/module/ui/night/primitives.js +3 -1
- package/lib/module/utils/snapshotProviderKit.js +156 -0
- package/lib/module/utils/stateTools.js +154 -0
- package/lib/typescript/commonjs/JsModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/hooks/index.d.ts +3 -1
- package/lib/typescript/commonjs/hooks/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/commonjs/hooks/useChangeLog.d.ts +38 -0
- package/lib/typescript/commonjs/hooks/useChangeLog.d.ts.map +1 -0
- package/lib/typescript/commonjs/hooks/useEventStoreEvents.d.ts +25 -0
- package/lib/typescript/commonjs/hooks/useEventStoreEvents.d.ts.map +1 -0
- package/lib/typescript/commonjs/hooks/usePersistedState.d.ts +34 -5
- package/lib/typescript/commonjs/hooks/usePersistedState.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +6 -1
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/storage/definePersistedSetting.d.ts +39 -0
- package/lib/typescript/commonjs/storage/definePersistedSetting.d.ts.map +1 -0
- package/lib/typescript/commonjs/storage/index.d.ts +1 -0
- package/lib/typescript/commonjs/storage/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/stores/ChangeLog.d.ts +100 -0
- package/lib/typescript/commonjs/stores/ChangeLog.d.ts.map +1 -0
- package/lib/typescript/commonjs/stores/createToolStore.d.ts +92 -0
- package/lib/typescript/commonjs/stores/createToolStore.d.ts.map +1 -0
- package/lib/typescript/commonjs/stores/index.d.ts +2 -0
- package/lib/typescript/commonjs/stores/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/sync/toolSyncAdapter.d.ts +66 -0
- package/lib/typescript/commonjs/sync/toolSyncAdapter.d.ts.map +1 -0
- package/lib/typescript/commonjs/sync/wireForm.d.ts +100 -0
- package/lib/typescript/commonjs/sync/wireForm.d.ts.map +1 -0
- package/lib/typescript/commonjs/tools/defineTool.d.ts +100 -0
- package/lib/typescript/commonjs/tools/defineTool.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ChangeRow.d.ts +52 -0
- package/lib/typescript/commonjs/ui/components/ChangeRow.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ChipStrip.d.ts +41 -0
- package/lib/typescript/commonjs/ui/components/ChipStrip.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/DetailViewToggle.d.ts +36 -0
- package/lib/typescript/commonjs/ui/components/DetailViewToggle.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/DevToolsCard.d.ts +8 -1
- package/lib/typescript/commonjs/ui/components/DevToolsCard.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/EntityFilterView.d.ts +51 -0
- package/lib/typescript/commonjs/ui/components/EntityFilterView.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ExportPreview.d.ts +48 -0
- package/lib/typescript/commonjs/ui/components/ExportPreview.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/InfoRow.d.ts +33 -0
- package/lib/typescript/commonjs/ui/components/InfoRow.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ModalHeader.d.ts +31 -1
- package/lib/typescript/commonjs/ui/components/ModalHeader.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/Pill.d.ts +38 -0
- package/lib/typescript/commonjs/ui/components/Pill.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ToggleRow.d.ts +33 -0
- package/lib/typescript/commonjs/ui/components/ToggleRow.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ToolFooter.d.ts +69 -0
- package/lib/typescript/commonjs/ui/components/ToolFooter.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/index.d.ts +9 -0
- package/lib/typescript/commonjs/ui/components/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/index.d.ts +1 -0
- package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/listPresets.d.ts +28 -0
- package/lib/typescript/commonjs/ui/listPresets.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/night/primitives.d.ts +3 -1
- package/lib/typescript/commonjs/ui/night/primitives.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/snapshotProviderKit.d.ts +81 -0
- package/lib/typescript/commonjs/utils/snapshotProviderKit.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/stateTools.d.ts +44 -0
- package/lib/typescript/commonjs/utils/stateTools.d.ts.map +1 -0
- package/lib/typescript/module/JsModal.d.ts.map +1 -1
- package/lib/typescript/module/hooks/index.d.ts +3 -1
- package/lib/typescript/module/hooks/index.d.ts.map +1 -1
- package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/module/hooks/useChangeLog.d.ts +38 -0
- package/lib/typescript/module/hooks/useChangeLog.d.ts.map +1 -0
- package/lib/typescript/module/hooks/useEventStoreEvents.d.ts +25 -0
- package/lib/typescript/module/hooks/useEventStoreEvents.d.ts.map +1 -0
- package/lib/typescript/module/hooks/usePersistedState.d.ts +34 -5
- package/lib/typescript/module/hooks/usePersistedState.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +6 -1
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/storage/definePersistedSetting.d.ts +39 -0
- package/lib/typescript/module/storage/definePersistedSetting.d.ts.map +1 -0
- package/lib/typescript/module/storage/index.d.ts +1 -0
- package/lib/typescript/module/storage/index.d.ts.map +1 -1
- package/lib/typescript/module/stores/ChangeLog.d.ts +100 -0
- package/lib/typescript/module/stores/ChangeLog.d.ts.map +1 -0
- package/lib/typescript/module/stores/createToolStore.d.ts +92 -0
- package/lib/typescript/module/stores/createToolStore.d.ts.map +1 -0
- package/lib/typescript/module/stores/index.d.ts +2 -0
- package/lib/typescript/module/stores/index.d.ts.map +1 -1
- package/lib/typescript/module/sync/toolSyncAdapter.d.ts +66 -0
- package/lib/typescript/module/sync/toolSyncAdapter.d.ts.map +1 -0
- package/lib/typescript/module/sync/wireForm.d.ts +100 -0
- package/lib/typescript/module/sync/wireForm.d.ts.map +1 -0
- package/lib/typescript/module/tools/defineTool.d.ts +100 -0
- package/lib/typescript/module/tools/defineTool.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ChangeRow.d.ts +52 -0
- package/lib/typescript/module/ui/components/ChangeRow.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ChipStrip.d.ts +41 -0
- package/lib/typescript/module/ui/components/ChipStrip.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/DetailViewToggle.d.ts +36 -0
- package/lib/typescript/module/ui/components/DetailViewToggle.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/DevToolsCard.d.ts +8 -1
- package/lib/typescript/module/ui/components/DevToolsCard.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/EntityFilterView.d.ts +51 -0
- package/lib/typescript/module/ui/components/EntityFilterView.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ExportPreview.d.ts +48 -0
- package/lib/typescript/module/ui/components/ExportPreview.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/InfoRow.d.ts +33 -0
- package/lib/typescript/module/ui/components/InfoRow.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ModalHeader.d.ts +31 -1
- package/lib/typescript/module/ui/components/ModalHeader.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/Pill.d.ts +38 -0
- package/lib/typescript/module/ui/components/Pill.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ToggleRow.d.ts +33 -0
- package/lib/typescript/module/ui/components/ToggleRow.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ToolFooter.d.ts +69 -0
- package/lib/typescript/module/ui/components/ToolFooter.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/index.d.ts +9 -0
- package/lib/typescript/module/ui/components/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/index.d.ts +1 -0
- package/lib/typescript/module/ui/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/listPresets.d.ts +28 -0
- package/lib/typescript/module/ui/listPresets.d.ts.map +1 -0
- package/lib/typescript/module/ui/night/primitives.d.ts +3 -1
- package/lib/typescript/module/ui/night/primitives.d.ts.map +1 -1
- package/lib/typescript/module/utils/snapshotProviderKit.d.ts +81 -0
- package/lib/typescript/module/utils/snapshotProviderKit.d.ts.map +1 -0
- package/lib/typescript/module/utils/stateTools.d.ts +44 -0
- package/lib/typescript/module/utils/stateTools.d.ts.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pill — the small caption chip every tool draws next to a row: a verdict
|
|
5
|
+
* ("UNUSED", "OVERSIZE"), a kind ("event", "transaction"), a link ("↔ 2"),
|
|
6
|
+
* a source ("MMKV"). Sixteen packages defined 150+ local pill styles that
|
|
7
|
+
* fall into five looks; those are the `variant`s here. Text is always in
|
|
8
|
+
* the pill's color (or the muted ink for `quiet`), never the series color
|
|
9
|
+
* of anything else.
|
|
10
|
+
*
|
|
11
|
+
* - `tinted` — color fill at 15% + border at 40% (scenarios, react-query chips)
|
|
12
|
+
* - `soft` — color fill at 20%, rounded, no border (events correlation badge)
|
|
13
|
+
* - `outline` — color border only (sentry envelope types)
|
|
14
|
+
* - `quiet` — neutral 6% white fill, muted text, optional color dot (assets)
|
|
15
|
+
* - `text` — bare colored caption, no chrome (images row badges)
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { StyleSheet, Text, View } from "react-native";
|
|
19
|
+
import { night } from "../night/nightTheme.js";
|
|
20
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
21
|
+
export function Pill({
|
|
22
|
+
label,
|
|
23
|
+
color = night.color.textSecondary,
|
|
24
|
+
variant = "tinted",
|
|
25
|
+
size = "xs",
|
|
26
|
+
mono = false,
|
|
27
|
+
uppercase,
|
|
28
|
+
dot = false,
|
|
29
|
+
icon,
|
|
30
|
+
testID,
|
|
31
|
+
style
|
|
32
|
+
}) {
|
|
33
|
+
const upper = uppercase ?? (variant === "tinted" || variant === "quiet" || variant === "text");
|
|
34
|
+
const textColor = variant === "quiet" ? night.color.textSecondary : color;
|
|
35
|
+
const chrome = variant === "tinted" ? {
|
|
36
|
+
backgroundColor: `${color}15`,
|
|
37
|
+
borderColor: `${color}40`,
|
|
38
|
+
borderWidth: 1
|
|
39
|
+
} : variant === "soft" ? {
|
|
40
|
+
backgroundColor: `${color}20`
|
|
41
|
+
} : variant === "outline" ? {
|
|
42
|
+
borderColor: color,
|
|
43
|
+
borderWidth: 1
|
|
44
|
+
} : variant === "quiet" ? {
|
|
45
|
+
backgroundColor: "rgba(255,255,255,0.06)"
|
|
46
|
+
} : {};
|
|
47
|
+
if (variant === "text") {
|
|
48
|
+
return /*#__PURE__*/_jsx(Text, {
|
|
49
|
+
style: [styles.text, size === "sm" && styles.textSm, mono && styles.mono, upper && styles.upper, {
|
|
50
|
+
color: textColor
|
|
51
|
+
}],
|
|
52
|
+
testID: testID,
|
|
53
|
+
children: label
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
57
|
+
style: [styles.pill, variant === "soft" && styles.pillSoft, size === "sm" && styles.pillSm, chrome, style],
|
|
58
|
+
children: [icon, dot && variant === "quiet" ? /*#__PURE__*/_jsx(View, {
|
|
59
|
+
style: [styles.dot, {
|
|
60
|
+
backgroundColor: color
|
|
61
|
+
}]
|
|
62
|
+
}) : null, /*#__PURE__*/_jsx(Text, {
|
|
63
|
+
style: [styles.text, size === "sm" && styles.textSm, mono && styles.mono, upper && styles.upper, {
|
|
64
|
+
color: textColor
|
|
65
|
+
}],
|
|
66
|
+
testID: testID,
|
|
67
|
+
children: label
|
|
68
|
+
})]
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
const styles = StyleSheet.create({
|
|
72
|
+
pill: {
|
|
73
|
+
flexDirection: "row",
|
|
74
|
+
alignItems: "center",
|
|
75
|
+
alignSelf: "flex-start",
|
|
76
|
+
gap: 4,
|
|
77
|
+
paddingHorizontal: 6,
|
|
78
|
+
paddingVertical: 2,
|
|
79
|
+
borderRadius: 4
|
|
80
|
+
},
|
|
81
|
+
pillSoft: {
|
|
82
|
+
paddingHorizontal: 8,
|
|
83
|
+
borderRadius: 10
|
|
84
|
+
},
|
|
85
|
+
pillSm: {
|
|
86
|
+
paddingHorizontal: 8,
|
|
87
|
+
paddingVertical: 3
|
|
88
|
+
},
|
|
89
|
+
dot: {
|
|
90
|
+
width: 5,
|
|
91
|
+
height: 5,
|
|
92
|
+
borderRadius: 2.5
|
|
93
|
+
},
|
|
94
|
+
text: {
|
|
95
|
+
fontSize: 10,
|
|
96
|
+
fontWeight: "600",
|
|
97
|
+
letterSpacing: 0.3
|
|
98
|
+
},
|
|
99
|
+
textSm: {
|
|
100
|
+
fontSize: 11
|
|
101
|
+
},
|
|
102
|
+
mono: {
|
|
103
|
+
fontFamily: "monospace"
|
|
104
|
+
},
|
|
105
|
+
upper: {
|
|
106
|
+
textTransform: "uppercase",
|
|
107
|
+
letterSpacing: 0.5,
|
|
108
|
+
fontWeight: "700"
|
|
109
|
+
}
|
|
110
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ToggleRow — a labeled switch row for a tool's settings surface.
|
|
5
|
+
*
|
|
6
|
+
* Every settings screen (impersonate, image-overlay, highlight-updates,
|
|
7
|
+
* perf-monitor, scenarios, storage, ask-buoy) drew its own `toggleRow` +
|
|
8
|
+
* `<Switch>` pair with the same night track colors. The native switch stays
|
|
9
|
+
* (a custom control would be a visible design change); the row chrome,
|
|
10
|
+
* the label/description stack and the accent/warning tone are shared.
|
|
11
|
+
*
|
|
12
|
+
* - `variant="card"` — an elevated bordered pill row (image-overlay)
|
|
13
|
+
* - `variant="plain"` — a bare list row for use inside a card (impersonate)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { StyleSheet, Switch, Text, View } from "react-native";
|
|
17
|
+
import { night } from "../night/nightTheme.js";
|
|
18
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
19
|
+
export function ToggleRow({
|
|
20
|
+
label,
|
|
21
|
+
description,
|
|
22
|
+
value,
|
|
23
|
+
onValueChange,
|
|
24
|
+
disabled = false,
|
|
25
|
+
tone = "accent",
|
|
26
|
+
accessory,
|
|
27
|
+
variant = "card",
|
|
28
|
+
emphasizeLabel = false,
|
|
29
|
+
testID,
|
|
30
|
+
style
|
|
31
|
+
}) {
|
|
32
|
+
const onColor = tone === "warning" ? night.color.warning : night.color.accent;
|
|
33
|
+
const isCard = variant === "card";
|
|
34
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
35
|
+
style: [styles.row, isCard ? styles.rowCard : styles.rowPlain, style],
|
|
36
|
+
children: [/*#__PURE__*/_jsxs(View, {
|
|
37
|
+
style: styles.info,
|
|
38
|
+
children: [/*#__PURE__*/_jsxs(View, {
|
|
39
|
+
style: styles.header,
|
|
40
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
41
|
+
style: [isCard ? styles.labelCard : styles.labelPlain, emphasizeLabel && {
|
|
42
|
+
color: onColor
|
|
43
|
+
}],
|
|
44
|
+
numberOfLines: 2,
|
|
45
|
+
children: label
|
|
46
|
+
}), accessory]
|
|
47
|
+
}), description ? /*#__PURE__*/_jsx(Text, {
|
|
48
|
+
style: styles.description,
|
|
49
|
+
children: description
|
|
50
|
+
}) : null]
|
|
51
|
+
}), /*#__PURE__*/_jsx(Switch, {
|
|
52
|
+
value: value,
|
|
53
|
+
onValueChange: onValueChange,
|
|
54
|
+
disabled: disabled,
|
|
55
|
+
testID: testID,
|
|
56
|
+
accessibilityLabel: label,
|
|
57
|
+
trackColor: isCard ? {
|
|
58
|
+
false: night.color.surfaceElevated,
|
|
59
|
+
true: onColor
|
|
60
|
+
} : {
|
|
61
|
+
false: night.color.border,
|
|
62
|
+
true: `${onColor}50`
|
|
63
|
+
},
|
|
64
|
+
thumbColor: isCard ? undefined : value ? onColor : night.color.knob
|
|
65
|
+
})]
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
const styles = StyleSheet.create({
|
|
69
|
+
row: {
|
|
70
|
+
flexDirection: "row",
|
|
71
|
+
alignItems: "center",
|
|
72
|
+
justifyContent: "space-between"
|
|
73
|
+
},
|
|
74
|
+
rowCard: {
|
|
75
|
+
backgroundColor: night.color.surfaceElevated,
|
|
76
|
+
borderRadius: 8,
|
|
77
|
+
borderWidth: 1,
|
|
78
|
+
borderColor: night.color.border,
|
|
79
|
+
paddingHorizontal: 12,
|
|
80
|
+
paddingVertical: 8
|
|
81
|
+
},
|
|
82
|
+
rowPlain: {
|
|
83
|
+
paddingVertical: 12,
|
|
84
|
+
paddingHorizontal: 12
|
|
85
|
+
},
|
|
86
|
+
info: {
|
|
87
|
+
flex: 1,
|
|
88
|
+
marginRight: 12
|
|
89
|
+
},
|
|
90
|
+
header: {
|
|
91
|
+
flexDirection: "row",
|
|
92
|
+
alignItems: "center",
|
|
93
|
+
gap: 8,
|
|
94
|
+
flexWrap: "wrap"
|
|
95
|
+
},
|
|
96
|
+
labelCard: {
|
|
97
|
+
fontSize: 13,
|
|
98
|
+
fontWeight: "500",
|
|
99
|
+
color: night.color.textSecondary
|
|
100
|
+
},
|
|
101
|
+
labelPlain: {
|
|
102
|
+
fontSize: 14,
|
|
103
|
+
fontWeight: "500",
|
|
104
|
+
color: night.color.text
|
|
105
|
+
},
|
|
106
|
+
description: {
|
|
107
|
+
fontSize: 12,
|
|
108
|
+
color: night.color.textTertiary,
|
|
109
|
+
lineHeight: 16,
|
|
110
|
+
marginTop: 3
|
|
111
|
+
}
|
|
112
|
+
});
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ToolFooter — the night glass bar pinned to the bottom of a tool: dark
|
|
5
|
+
* backing over the star field, a hairline on top, safe-area padding when
|
|
6
|
+
* docked as a sheet, rounded corners when floating.
|
|
7
|
+
*
|
|
8
|
+
* `EventStepperFooter` draws this bar for the Previous/Next case; the
|
|
9
|
+
* images and react-query tools each re-drew it for their action bars with
|
|
10
|
+
* a comment saying "matches EventStepperFooter". This is that bar as a
|
|
11
|
+
* container, plus `FooterButton` — the mono uppercase plate button those
|
|
12
|
+
* action bars are made of — and the caption/message lines above the row.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
|
|
16
|
+
import { night } from "../night/nightTheme.js";
|
|
17
|
+
import { useSafeAreaInsets } from "../../hooks/useSafeAreaInsets.js";
|
|
18
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
19
|
+
export function ToolFooter({
|
|
20
|
+
children,
|
|
21
|
+
safeArea = true,
|
|
22
|
+
paddingBottom = 12,
|
|
23
|
+
floating = false,
|
|
24
|
+
absolute = false,
|
|
25
|
+
gap = 8,
|
|
26
|
+
style,
|
|
27
|
+
testID
|
|
28
|
+
}) {
|
|
29
|
+
const insets = useSafeAreaInsets();
|
|
30
|
+
const bottom = typeof safeArea === "number" ? safeArea + insets.bottom : safeArea ? paddingBottom + insets.bottom : paddingBottom;
|
|
31
|
+
return /*#__PURE__*/_jsx(View, {
|
|
32
|
+
style: [styles.footer, floating && styles.footerFloating, absolute && styles.footerAbsolute, {
|
|
33
|
+
paddingBottom: bottom,
|
|
34
|
+
gap
|
|
35
|
+
}, style],
|
|
36
|
+
testID: testID,
|
|
37
|
+
children: children
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** A row of footer buttons. */
|
|
42
|
+
export function FooterRow({
|
|
43
|
+
children,
|
|
44
|
+
style
|
|
45
|
+
}) {
|
|
46
|
+
return /*#__PURE__*/_jsx(View, {
|
|
47
|
+
style: [styles.row, style],
|
|
48
|
+
children: children
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Tracking caption above a row ("MASS ACTIONS — every image on screen"). */
|
|
53
|
+
export function FooterCaption({
|
|
54
|
+
children,
|
|
55
|
+
style
|
|
56
|
+
}) {
|
|
57
|
+
return /*#__PURE__*/_jsx(Text, {
|
|
58
|
+
style: [styles.caption, style],
|
|
59
|
+
numberOfLines: 1,
|
|
60
|
+
children: children
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Mono feedback line ("Restored 3 images"). */
|
|
65
|
+
export function FooterMessage({
|
|
66
|
+
children,
|
|
67
|
+
tone = "info",
|
|
68
|
+
style
|
|
69
|
+
}) {
|
|
70
|
+
return /*#__PURE__*/_jsx(Text, {
|
|
71
|
+
style: [styles.message, tone === "muted" && styles.messageMuted, style],
|
|
72
|
+
numberOfLines: 1,
|
|
73
|
+
children: children
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
export function FooterButton({
|
|
77
|
+
label,
|
|
78
|
+
onPress,
|
|
79
|
+
accent = false,
|
|
80
|
+
active = false,
|
|
81
|
+
disabled = false,
|
|
82
|
+
icon,
|
|
83
|
+
flex = true,
|
|
84
|
+
size = "sm",
|
|
85
|
+
testID,
|
|
86
|
+
accessibilityLabel,
|
|
87
|
+
style
|
|
88
|
+
}) {
|
|
89
|
+
return /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
90
|
+
onPress: onPress,
|
|
91
|
+
disabled: disabled,
|
|
92
|
+
activeOpacity: 0.7,
|
|
93
|
+
accessibilityRole: "button",
|
|
94
|
+
accessibilityLabel: accessibilityLabel ?? label,
|
|
95
|
+
accessibilityState: {
|
|
96
|
+
disabled,
|
|
97
|
+
selected: active
|
|
98
|
+
},
|
|
99
|
+
testID: testID,
|
|
100
|
+
style: [styles.button, flex ? styles.buttonFlex : styles.buttonFixed, size === "md" && styles.buttonMd, active && styles.buttonActive, disabled && styles.disabled, style],
|
|
101
|
+
children: [icon, /*#__PURE__*/_jsx(Text, {
|
|
102
|
+
style: [styles.buttonText, size === "md" && styles.buttonTextMd, accent && !disabled && styles.buttonTextAccent, active && styles.buttonTextActive, disabled && styles.buttonTextDisabled],
|
|
103
|
+
children: label
|
|
104
|
+
})]
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
const styles = StyleSheet.create({
|
|
108
|
+
footer: {
|
|
109
|
+
paddingHorizontal: 12,
|
|
110
|
+
paddingTop: 10,
|
|
111
|
+
// Dark glass over the star field — the same bar EventStepperFooter draws.
|
|
112
|
+
backgroundColor: "rgba(5, 5, 5, 0.92)",
|
|
113
|
+
borderTopWidth: 1,
|
|
114
|
+
borderTopColor: night.color.border
|
|
115
|
+
},
|
|
116
|
+
footerFloating: {
|
|
117
|
+
borderBottomLeftRadius: 14,
|
|
118
|
+
borderBottomRightRadius: 14
|
|
119
|
+
},
|
|
120
|
+
footerAbsolute: {
|
|
121
|
+
position: "absolute",
|
|
122
|
+
left: 0,
|
|
123
|
+
right: 0,
|
|
124
|
+
bottom: 0
|
|
125
|
+
},
|
|
126
|
+
row: {
|
|
127
|
+
flexDirection: "row",
|
|
128
|
+
alignItems: "center",
|
|
129
|
+
gap: 6
|
|
130
|
+
},
|
|
131
|
+
caption: {
|
|
132
|
+
color: night.color.textTertiary,
|
|
133
|
+
fontSize: 9,
|
|
134
|
+
fontWeight: "700",
|
|
135
|
+
letterSpacing: 0.8
|
|
136
|
+
},
|
|
137
|
+
message: {
|
|
138
|
+
color: night.color.info,
|
|
139
|
+
fontSize: 10,
|
|
140
|
+
fontFamily: "monospace"
|
|
141
|
+
},
|
|
142
|
+
messageMuted: {
|
|
143
|
+
color: night.color.textTertiary,
|
|
144
|
+
fontFamily: undefined
|
|
145
|
+
},
|
|
146
|
+
button: {
|
|
147
|
+
flexDirection: "row",
|
|
148
|
+
alignItems: "center",
|
|
149
|
+
justifyContent: "center",
|
|
150
|
+
gap: 6,
|
|
151
|
+
paddingVertical: 8,
|
|
152
|
+
// No horizontal padding: six of these share one row on a phone, and the
|
|
153
|
+
// mono uppercase label needs every point it can get before it wraps.
|
|
154
|
+
paddingHorizontal: 0,
|
|
155
|
+
borderRadius: 6,
|
|
156
|
+
backgroundColor: night.color.button,
|
|
157
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
158
|
+
borderColor: night.color.border
|
|
159
|
+
},
|
|
160
|
+
buttonFlex: {
|
|
161
|
+
flex: 1
|
|
162
|
+
},
|
|
163
|
+
buttonFixed: {
|
|
164
|
+
paddingHorizontal: 10
|
|
165
|
+
},
|
|
166
|
+
buttonMd: {
|
|
167
|
+
paddingVertical: 8
|
|
168
|
+
},
|
|
169
|
+
buttonActive: {
|
|
170
|
+
backgroundColor: night.color.accentSoft,
|
|
171
|
+
borderColor: night.color.accentBorderStrong
|
|
172
|
+
},
|
|
173
|
+
buttonText: {
|
|
174
|
+
fontSize: 10,
|
|
175
|
+
fontWeight: "600",
|
|
176
|
+
color: night.color.textSecondary,
|
|
177
|
+
fontFamily: "monospace",
|
|
178
|
+
textTransform: "uppercase"
|
|
179
|
+
},
|
|
180
|
+
buttonTextMd: {
|
|
181
|
+
fontSize: 11,
|
|
182
|
+
color: night.color.text
|
|
183
|
+
},
|
|
184
|
+
buttonTextAccent: {
|
|
185
|
+
color: night.color.warning
|
|
186
|
+
},
|
|
187
|
+
buttonTextActive: {
|
|
188
|
+
color: night.color.accent
|
|
189
|
+
},
|
|
190
|
+
buttonTextDisabled: {
|
|
191
|
+
color: night.color.textTertiary
|
|
192
|
+
},
|
|
193
|
+
disabled: {
|
|
194
|
+
opacity: 0.4
|
|
195
|
+
}
|
|
196
|
+
});
|
|
@@ -40,4 +40,13 @@ export { PowerToggleButton } from "./PowerToggleButton.js";
|
|
|
40
40
|
export { ExpandedInfoRow, PillBadge } from "./ExpandedInfoRow.js";
|
|
41
41
|
|
|
42
42
|
// EventHistoryViewer components
|
|
43
|
-
export { EventHistoryViewer, ViewToggleCards, DiffModeTabs, CompareBar, EventPickerModal } from "./EventHistoryViewer/index.js";
|
|
43
|
+
export { EventHistoryViewer, ViewToggleCards, DiffModeTabs, CompareBar, EventPickerModal } from "./EventHistoryViewer/index.js";
|
|
44
|
+
export { InfoRow } from "./InfoRow.js";
|
|
45
|
+
export { DetailViewToggle } from "./DetailViewToggle.js";
|
|
46
|
+
export { ChangeRow } from "./ChangeRow.js";
|
|
47
|
+
export { Pill } from "./Pill.js";
|
|
48
|
+
export { ToolFooter, FooterRow, FooterCaption, FooterMessage, FooterButton } from "./ToolFooter.js";
|
|
49
|
+
export { EntityFilterView } from "./EntityFilterView.js";
|
|
50
|
+
export { ToggleRow } from "./ToggleRow.js";
|
|
51
|
+
export { ChipStrip, useChipTap } from "./ChipStrip.js";
|
|
52
|
+
export { ExportPreview, sizeWarningLevel } from "./ExportPreview.js";
|
package/lib/module/ui/index.js
CHANGED
|
@@ -18,4 +18,7 @@ export { CyberpunkSectionButton } from "./console/CyberpunkSectionButton.js";
|
|
|
18
18
|
export * from "./gameUI/index.js";
|
|
19
19
|
|
|
20
20
|
// Otto — the Buoy mascot (see OTTO_PLACEMENT_PLAN.md for where he belongs)
|
|
21
|
-
export * from "./otto/index.js";
|
|
21
|
+
export * from "./otto/index.js";
|
|
22
|
+
|
|
23
|
+
// FlatList presets (tuned window/batch values + the E2E clipping guard)
|
|
24
|
+
export { EVENT_LIST_PRESET, LOG_LIST_PRESET, CLIP_OFFSCREEN_CELLS } from "./listPresets.js";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* FlatList presets for tool lists — the tuned window/batch values and the
|
|
5
|
+
* E2E clipping guard that eleven list sites carried as copy-pasted props.
|
|
6
|
+
*
|
|
7
|
+
* Spread them onto a FlatList: `<FlatList {...EVENT_LIST_PRESET} … />`.
|
|
8
|
+
* A tool that later moves to FlashList changes this file, not eleven.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* `removeClippedSubviews` is off in E2E bundles: clipped rows leave the
|
|
13
|
+
* hierarchy entirely, so a row past the fold reads to the test as "the tool
|
|
14
|
+
* stopped capturing".
|
|
15
|
+
*/
|
|
16
|
+
export const CLIP_OFFSCREEN_CELLS = !(typeof process !== "undefined" && process.env?.EXPO_PUBLIC_E2E);
|
|
17
|
+
/**
|
|
18
|
+
* Event / change / request lists: rows are tall-ish and arrive in bursts.
|
|
19
|
+
* Window and batch values are the "tuned" winner of the buoy-optimize
|
|
20
|
+
* batch run on the network tool (2026-07-06, batch-1783396983529-6l7w).
|
|
21
|
+
*/
|
|
22
|
+
export const EVENT_LIST_PRESET = {
|
|
23
|
+
initialNumToRender: 12,
|
|
24
|
+
maxToRenderPerBatch: 8,
|
|
25
|
+
windowSize: 5,
|
|
26
|
+
updateCellsBatchingPeriod: 50,
|
|
27
|
+
removeClippedSubviews: CLIP_OFFSCREEN_CELLS
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Log tails (console, sentry): rows are short single lines, the list is
|
|
32
|
+
* read from the bottom, and a scroll-to-end must not land on blank cells.
|
|
33
|
+
*/
|
|
34
|
+
export const LOG_LIST_PRESET = {
|
|
35
|
+
initialNumToRender: 30,
|
|
36
|
+
maxToRenderPerBatch: 30,
|
|
37
|
+
windowSize: 21,
|
|
38
|
+
removeClippedSubviews: CLIP_OFFSCREEN_CELLS
|
|
39
|
+
};
|
|
@@ -154,12 +154,14 @@ export function NightChip({
|
|
|
154
154
|
selected,
|
|
155
155
|
onPress,
|
|
156
156
|
disabled,
|
|
157
|
-
icon
|
|
157
|
+
icon,
|
|
158
|
+
testID
|
|
158
159
|
}) {
|
|
159
160
|
return /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
160
161
|
activeOpacity: 0.7,
|
|
161
162
|
disabled: disabled || !onPress,
|
|
162
163
|
onPress: onPress,
|
|
164
|
+
testID: testID,
|
|
163
165
|
style: [styles.chip, selected ? styles.chipSelected : null, disabled ? styles.chipDisabled : null],
|
|
164
166
|
children: [icon, /*#__PURE__*/_jsx(Text, {
|
|
165
167
|
style: [styles.chipText, selected ? styles.chipTextSelected : null],
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* snapshotProviderKit — the parts of a Time Machine `StateSnapshotProvider`
|
|
5
|
+
* that are the same for every source.
|
|
6
|
+
*
|
|
7
|
+
* storage, redux, zustand, jotai and react-query each register a provider
|
|
8
|
+
* (see stateSnapshotRegistry.ts). What differs is how they read and write
|
|
9
|
+
* their source. What was copied five times is:
|
|
10
|
+
*
|
|
11
|
+
* - the restore SCOPE gate: `excludeKeys` (touch all but these) and
|
|
12
|
+
* `includeKeys` (touch only these), the "N item(s) excluded by you"
|
|
13
|
+
* warning, and the empty `StateSnapshotRestoreResult`;
|
|
14
|
+
* - the preview VERDICT ladder: removed → added → unchanged → too-large →
|
|
15
|
+
* changed, with the 256 KB per-item render cap;
|
|
16
|
+
* - the "won't apply" override: a difference restore cannot apply must say
|
|
17
|
+
* so instead of rendering as a green change.
|
|
18
|
+
*
|
|
19
|
+
* The parts that stay per-tool are the ones that matter: redux verifies the
|
|
20
|
+
* jump by reference identity, zustand grafts action functions back, jotai
|
|
21
|
+
* leaves derived atoms to recompute, storage gates MMKV buffers and
|
|
22
|
+
* biometric keys, react-query diffs a comparable projection.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { boundedDeepEqual, jsonLikelyLargerThan } from "../dataViewer/objectDiff.js";
|
|
26
|
+
/** Beyond this a preview item is "too-large": restore still applies it, the diff isn't drawn. */
|
|
27
|
+
export const PREVIEW_ITEM_RENDER_BYTE_LIMIT = 256 * 1024;
|
|
28
|
+
/**
|
|
29
|
+
* Both option lists use preview item keys, and both mean "leave everything
|
|
30
|
+
* else untouched in BOTH directions". `includeKeys` wins when present;
|
|
31
|
+
* `excludeKeys` still applies on top.
|
|
32
|
+
*/
|
|
33
|
+
export function createRestoreScope(options) {
|
|
34
|
+
const excludedSet = new Set(options?.excludeKeys ?? []);
|
|
35
|
+
const includedSet = options?.includeKeys ? new Set(options.includeKeys) : null;
|
|
36
|
+
let excludedHits = 0;
|
|
37
|
+
const touch = key => !excludedSet.has(key) && (!includedSet || includedSet.has(key));
|
|
38
|
+
return {
|
|
39
|
+
touch,
|
|
40
|
+
allows(key) {
|
|
41
|
+
if (touch(key)) return true;
|
|
42
|
+
excludedHits += 1;
|
|
43
|
+
return false;
|
|
44
|
+
},
|
|
45
|
+
countExcluded(n) {
|
|
46
|
+
excludedHits += n;
|
|
47
|
+
},
|
|
48
|
+
get excludedHits() {
|
|
49
|
+
return excludedHits;
|
|
50
|
+
},
|
|
51
|
+
excludedWarning(noun) {
|
|
52
|
+
return excludedHits > 0 ? `${excludedHits} ${noun} excluded by you` : null;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** A fresh, successful, empty result to accumulate into. */
|
|
58
|
+
export function emptyRestoreResult() {
|
|
59
|
+
return {
|
|
60
|
+
ok: true,
|
|
61
|
+
applied: 0,
|
|
62
|
+
skipped: [],
|
|
63
|
+
warnings: []
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** A failed result with one warning (an empty or unusable snapshot). */
|
|
68
|
+
export function failedRestore(warning) {
|
|
69
|
+
return {
|
|
70
|
+
ok: false,
|
|
71
|
+
applied: 0,
|
|
72
|
+
skipped: [],
|
|
73
|
+
warnings: [warning]
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** A failed result with one skipped item and its reason. */
|
|
78
|
+
export function skippedRestore(id, reason) {
|
|
79
|
+
return {
|
|
80
|
+
ok: false,
|
|
81
|
+
applied: 0,
|
|
82
|
+
skipped: [{
|
|
83
|
+
id,
|
|
84
|
+
reason
|
|
85
|
+
}],
|
|
86
|
+
warnings: []
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The verdict ladder: removed → added → unchanged → too-large → changed.
|
|
91
|
+
* Callers layer source-specific verdicts (`wont-apply`, `recomputes`) on top
|
|
92
|
+
* with `wontApply()`.
|
|
93
|
+
*/
|
|
94
|
+
export function classifyPreviewItem(input, options = {}) {
|
|
95
|
+
const {
|
|
96
|
+
key,
|
|
97
|
+
label,
|
|
98
|
+
oldValue,
|
|
99
|
+
newValue,
|
|
100
|
+
inOld,
|
|
101
|
+
inNew
|
|
102
|
+
} = input;
|
|
103
|
+
if (!inNew) return {
|
|
104
|
+
key,
|
|
105
|
+
label,
|
|
106
|
+
verdict: "removed",
|
|
107
|
+
oldValue
|
|
108
|
+
};
|
|
109
|
+
if (!inOld) return {
|
|
110
|
+
key,
|
|
111
|
+
label,
|
|
112
|
+
verdict: "added",
|
|
113
|
+
newValue
|
|
114
|
+
};
|
|
115
|
+
const equal = options.equal ?? boundedDeepEqual;
|
|
116
|
+
if (equal(oldValue, newValue)) return {
|
|
117
|
+
key,
|
|
118
|
+
label,
|
|
119
|
+
verdict: "unchanged"
|
|
120
|
+
};
|
|
121
|
+
const tooLarge = options.tooLarge ?? (value => jsonLikelyLargerThan(value, PREVIEW_ITEM_RENDER_BYTE_LIMIT));
|
|
122
|
+
if (tooLarge(oldValue) || tooLarge(newValue)) {
|
|
123
|
+
return {
|
|
124
|
+
key,
|
|
125
|
+
label,
|
|
126
|
+
verdict: "too-large",
|
|
127
|
+
reason: options.tooLargeReason ?? "value too large to render a diff — restore still applies it"
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
key,
|
|
132
|
+
label,
|
|
133
|
+
verdict: "changed",
|
|
134
|
+
oldValue,
|
|
135
|
+
newValue
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Mark an item as something restore cannot apply. An unchanged item is left
|
|
141
|
+
* alone — there is nothing to apply, so nothing is being refused.
|
|
142
|
+
*/
|
|
143
|
+
export function wontApply(item, reason) {
|
|
144
|
+
if (item.verdict === "unchanged") return item;
|
|
145
|
+
return {
|
|
146
|
+
...item,
|
|
147
|
+
verdict: "wont-apply",
|
|
148
|
+
reason
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Every key present in either record, once. */
|
|
153
|
+
export function unionKeys(a, b) {
|
|
154
|
+
const keysOf = r => r === undefined ? [] : r instanceof Map ? Array.from(r.keys()) : Object.keys(r);
|
|
155
|
+
return new Set([...keysOf(a), ...keysOf(b)]);
|
|
156
|
+
}
|