@buoy-gg/shared-ui 7.0.32 → 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.
Files changed (237) hide show
  1. package/lib/commonjs/JsModal.js +70 -28
  2. package/lib/commonjs/hooks/index.js +26 -0
  3. package/lib/commonjs/hooks/safe-area-impl.js +1 -1
  4. package/lib/commonjs/hooks/useChangeLog.js +55 -0
  5. package/lib/commonjs/hooks/useEventStoreEvents.js +65 -0
  6. package/lib/commonjs/hooks/usePersistedState.js +45 -10
  7. package/lib/commonjs/index.js +143 -0
  8. package/lib/commonjs/storage/definePersistedSetting.js +67 -0
  9. package/lib/commonjs/storage/devToolsStorageKeys.js +12 -0
  10. package/lib/commonjs/storage/index.js +8 -1
  11. package/lib/commonjs/stores/ChangeLog.js +197 -0
  12. package/lib/commonjs/stores/createToolStore.js +175 -0
  13. package/lib/commonjs/stores/index.js +15 -1
  14. package/lib/commonjs/sync/toolSyncAdapter.js +63 -0
  15. package/lib/commonjs/sync/wireForm.js +172 -0
  16. package/lib/commonjs/tools/defineTool.js +79 -0
  17. package/lib/commonjs/ui/components/ChangeRow.js +110 -0
  18. package/lib/commonjs/ui/components/ChipStrip.js +94 -0
  19. package/lib/commonjs/ui/components/DetailViewToggle.js +130 -0
  20. package/lib/commonjs/ui/components/DevToolsCard.js +3 -1
  21. package/lib/commonjs/ui/components/EmptyState.js +10 -2
  22. package/lib/commonjs/ui/components/EntityFilterView.js +354 -0
  23. package/lib/commonjs/ui/components/ExportPreview.js +174 -0
  24. package/lib/commonjs/ui/components/InfoRow.js +90 -0
  25. package/lib/commonjs/ui/components/ModalHeader.js +40 -7
  26. package/lib/commonjs/ui/components/Pill.js +114 -0
  27. package/lib/commonjs/ui/components/ToggleRow.js +116 -0
  28. package/lib/commonjs/ui/components/ToolEmptyState.js +154 -0
  29. package/lib/commonjs/ui/components/ToolFooter.js +204 -0
  30. package/lib/commonjs/ui/components/WindowControls.js +8 -5
  31. package/lib/commonjs/ui/components/index.js +113 -1
  32. package/lib/commonjs/ui/index.js +36 -2
  33. package/lib/commonjs/ui/listPresets.js +43 -0
  34. package/lib/commonjs/ui/night/primitives.js +3 -1
  35. package/lib/commonjs/ui/otto/OttoSprite.js +510 -0
  36. package/lib/commonjs/ui/otto/index.js +38 -0
  37. package/lib/commonjs/ui/otto/ottoEngine.js +2734 -0
  38. package/lib/commonjs/ui/otto/ottoSheet.js +191 -0
  39. package/lib/commonjs/utils/snapshotProviderKit.js +167 -0
  40. package/lib/commonjs/utils/stateTools.js +160 -0
  41. package/lib/module/JsModal.js +70 -28
  42. package/lib/module/hooks/index.js +3 -1
  43. package/lib/module/hooks/safe-area-impl.js +1 -1
  44. package/lib/module/hooks/useChangeLog.js +50 -0
  45. package/lib/module/hooks/useEventStoreEvents.js +61 -0
  46. package/lib/module/hooks/usePersistedState.js +44 -10
  47. package/lib/module/index.js +11 -1
  48. package/lib/module/storage/definePersistedSetting.js +63 -0
  49. package/lib/module/storage/devToolsStorageKeys.js +12 -0
  50. package/lib/module/storage/index.js +2 -1
  51. package/lib/module/stores/ChangeLog.js +192 -0
  52. package/lib/module/stores/createToolStore.js +171 -0
  53. package/lib/module/stores/index.js +3 -1
  54. package/lib/module/sync/toolSyncAdapter.js +58 -0
  55. package/lib/module/sync/wireForm.js +159 -0
  56. package/lib/module/tools/defineTool.js +74 -0
  57. package/lib/module/ui/components/ChangeRow.js +105 -0
  58. package/lib/module/ui/components/ChipStrip.js +91 -0
  59. package/lib/module/ui/components/DetailViewToggle.js +125 -0
  60. package/lib/module/ui/components/DevToolsCard.js +3 -1
  61. package/lib/module/ui/components/EmptyState.js +10 -2
  62. package/lib/module/ui/components/EntityFilterView.js +350 -0
  63. package/lib/module/ui/components/ExportPreview.js +169 -0
  64. package/lib/module/ui/components/InfoRow.js +86 -0
  65. package/lib/module/ui/components/ModalHeader.js +40 -7
  66. package/lib/module/ui/components/Pill.js +110 -0
  67. package/lib/module/ui/components/ToggleRow.js +112 -0
  68. package/lib/module/ui/components/ToolEmptyState.js +149 -0
  69. package/lib/module/ui/components/ToolFooter.js +196 -0
  70. package/lib/module/ui/components/WindowControls.js +8 -5
  71. package/lib/module/ui/components/index.js +13 -1
  72. package/lib/module/ui/index.js +7 -1
  73. package/lib/module/ui/listPresets.js +39 -0
  74. package/lib/module/ui/night/primitives.js +3 -1
  75. package/lib/module/ui/otto/OttoSprite.js +496 -0
  76. package/lib/module/ui/otto/index.js +20 -0
  77. package/lib/module/ui/otto/ottoEngine.js +2726 -0
  78. package/lib/module/ui/otto/ottoSheet.js +180 -0
  79. package/lib/module/utils/snapshotProviderKit.js +156 -0
  80. package/lib/module/utils/stateTools.js +154 -0
  81. package/lib/typescript/commonjs/JsModal.d.ts.map +1 -1
  82. package/lib/typescript/commonjs/hooks/index.d.ts +3 -1
  83. package/lib/typescript/commonjs/hooks/index.d.ts.map +1 -1
  84. package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
  85. package/lib/typescript/commonjs/hooks/useChangeLog.d.ts +38 -0
  86. package/lib/typescript/commonjs/hooks/useChangeLog.d.ts.map +1 -0
  87. package/lib/typescript/commonjs/hooks/useEventStoreEvents.d.ts +25 -0
  88. package/lib/typescript/commonjs/hooks/useEventStoreEvents.d.ts.map +1 -0
  89. package/lib/typescript/commonjs/hooks/usePersistedState.d.ts +34 -5
  90. package/lib/typescript/commonjs/hooks/usePersistedState.d.ts.map +1 -1
  91. package/lib/typescript/commonjs/index.d.ts +6 -1
  92. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  93. package/lib/typescript/commonjs/storage/definePersistedSetting.d.ts +39 -0
  94. package/lib/typescript/commonjs/storage/definePersistedSetting.d.ts.map +1 -0
  95. package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts +12 -0
  96. package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts.map +1 -1
  97. package/lib/typescript/commonjs/storage/index.d.ts +1 -0
  98. package/lib/typescript/commonjs/storage/index.d.ts.map +1 -1
  99. package/lib/typescript/commonjs/stores/ChangeLog.d.ts +100 -0
  100. package/lib/typescript/commonjs/stores/ChangeLog.d.ts.map +1 -0
  101. package/lib/typescript/commonjs/stores/createToolStore.d.ts +92 -0
  102. package/lib/typescript/commonjs/stores/createToolStore.d.ts.map +1 -0
  103. package/lib/typescript/commonjs/stores/index.d.ts +2 -0
  104. package/lib/typescript/commonjs/stores/index.d.ts.map +1 -1
  105. package/lib/typescript/commonjs/sync/toolSyncAdapter.d.ts +66 -0
  106. package/lib/typescript/commonjs/sync/toolSyncAdapter.d.ts.map +1 -0
  107. package/lib/typescript/commonjs/sync/wireForm.d.ts +100 -0
  108. package/lib/typescript/commonjs/sync/wireForm.d.ts.map +1 -0
  109. package/lib/typescript/commonjs/tools/defineTool.d.ts +100 -0
  110. package/lib/typescript/commonjs/tools/defineTool.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/ui/components/ChangeRow.d.ts +52 -0
  112. package/lib/typescript/commonjs/ui/components/ChangeRow.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/ui/components/ChipStrip.d.ts +41 -0
  114. package/lib/typescript/commonjs/ui/components/ChipStrip.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/ui/components/DetailViewToggle.d.ts +36 -0
  116. package/lib/typescript/commonjs/ui/components/DetailViewToggle.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/ui/components/DevToolsCard.d.ts +8 -1
  118. package/lib/typescript/commonjs/ui/components/DevToolsCard.d.ts.map +1 -1
  119. package/lib/typescript/commonjs/ui/components/EmptyState.d.ts +14 -1
  120. package/lib/typescript/commonjs/ui/components/EmptyState.d.ts.map +1 -1
  121. package/lib/typescript/commonjs/ui/components/EntityFilterView.d.ts +51 -0
  122. package/lib/typescript/commonjs/ui/components/EntityFilterView.d.ts.map +1 -0
  123. package/lib/typescript/commonjs/ui/components/ExportPreview.d.ts +48 -0
  124. package/lib/typescript/commonjs/ui/components/ExportPreview.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/ui/components/InfoRow.d.ts +33 -0
  126. package/lib/typescript/commonjs/ui/components/InfoRow.d.ts.map +1 -0
  127. package/lib/typescript/commonjs/ui/components/ModalHeader.d.ts +31 -1
  128. package/lib/typescript/commonjs/ui/components/ModalHeader.d.ts.map +1 -1
  129. package/lib/typescript/commonjs/ui/components/Pill.d.ts +38 -0
  130. package/lib/typescript/commonjs/ui/components/Pill.d.ts.map +1 -0
  131. package/lib/typescript/commonjs/ui/components/ToggleRow.d.ts +33 -0
  132. package/lib/typescript/commonjs/ui/components/ToggleRow.d.ts.map +1 -0
  133. package/lib/typescript/commonjs/ui/components/ToolEmptyState.d.ts +113 -0
  134. package/lib/typescript/commonjs/ui/components/ToolEmptyState.d.ts.map +1 -0
  135. package/lib/typescript/commonjs/ui/components/ToolFooter.d.ts +69 -0
  136. package/lib/typescript/commonjs/ui/components/ToolFooter.d.ts.map +1 -0
  137. package/lib/typescript/commonjs/ui/components/WindowControls.d.ts +7 -1
  138. package/lib/typescript/commonjs/ui/components/WindowControls.d.ts.map +1 -1
  139. package/lib/typescript/commonjs/ui/components/index.d.ts +11 -0
  140. package/lib/typescript/commonjs/ui/components/index.d.ts.map +1 -1
  141. package/lib/typescript/commonjs/ui/index.d.ts +2 -0
  142. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  143. package/lib/typescript/commonjs/ui/listPresets.d.ts +28 -0
  144. package/lib/typescript/commonjs/ui/listPresets.d.ts.map +1 -0
  145. package/lib/typescript/commonjs/ui/night/primitives.d.ts +3 -1
  146. package/lib/typescript/commonjs/ui/night/primitives.d.ts.map +1 -1
  147. package/lib/typescript/commonjs/ui/otto/OttoSprite.d.ts +103 -0
  148. package/lib/typescript/commonjs/ui/otto/OttoSprite.d.ts.map +1 -0
  149. package/lib/typescript/commonjs/ui/otto/index.d.ts +19 -0
  150. package/lib/typescript/commonjs/ui/otto/index.d.ts.map +1 -0
  151. package/lib/typescript/commonjs/ui/otto/ottoEngine.d.ts +2205 -0
  152. package/lib/typescript/commonjs/ui/otto/ottoEngine.d.ts.map +1 -0
  153. package/lib/typescript/commonjs/ui/otto/ottoSheet.d.ts +73 -0
  154. package/lib/typescript/commonjs/ui/otto/ottoSheet.d.ts.map +1 -0
  155. package/lib/typescript/commonjs/utils/snapshotProviderKit.d.ts +81 -0
  156. package/lib/typescript/commonjs/utils/snapshotProviderKit.d.ts.map +1 -0
  157. package/lib/typescript/commonjs/utils/stateTools.d.ts +44 -0
  158. package/lib/typescript/commonjs/utils/stateTools.d.ts.map +1 -0
  159. package/lib/typescript/module/JsModal.d.ts.map +1 -1
  160. package/lib/typescript/module/hooks/index.d.ts +3 -1
  161. package/lib/typescript/module/hooks/index.d.ts.map +1 -1
  162. package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
  163. package/lib/typescript/module/hooks/useChangeLog.d.ts +38 -0
  164. package/lib/typescript/module/hooks/useChangeLog.d.ts.map +1 -0
  165. package/lib/typescript/module/hooks/useEventStoreEvents.d.ts +25 -0
  166. package/lib/typescript/module/hooks/useEventStoreEvents.d.ts.map +1 -0
  167. package/lib/typescript/module/hooks/usePersistedState.d.ts +34 -5
  168. package/lib/typescript/module/hooks/usePersistedState.d.ts.map +1 -1
  169. package/lib/typescript/module/index.d.ts +6 -1
  170. package/lib/typescript/module/index.d.ts.map +1 -1
  171. package/lib/typescript/module/storage/definePersistedSetting.d.ts +39 -0
  172. package/lib/typescript/module/storage/definePersistedSetting.d.ts.map +1 -0
  173. package/lib/typescript/module/storage/devToolsStorageKeys.d.ts +12 -0
  174. package/lib/typescript/module/storage/devToolsStorageKeys.d.ts.map +1 -1
  175. package/lib/typescript/module/storage/index.d.ts +1 -0
  176. package/lib/typescript/module/storage/index.d.ts.map +1 -1
  177. package/lib/typescript/module/stores/ChangeLog.d.ts +100 -0
  178. package/lib/typescript/module/stores/ChangeLog.d.ts.map +1 -0
  179. package/lib/typescript/module/stores/createToolStore.d.ts +92 -0
  180. package/lib/typescript/module/stores/createToolStore.d.ts.map +1 -0
  181. package/lib/typescript/module/stores/index.d.ts +2 -0
  182. package/lib/typescript/module/stores/index.d.ts.map +1 -1
  183. package/lib/typescript/module/sync/toolSyncAdapter.d.ts +66 -0
  184. package/lib/typescript/module/sync/toolSyncAdapter.d.ts.map +1 -0
  185. package/lib/typescript/module/sync/wireForm.d.ts +100 -0
  186. package/lib/typescript/module/sync/wireForm.d.ts.map +1 -0
  187. package/lib/typescript/module/tools/defineTool.d.ts +100 -0
  188. package/lib/typescript/module/tools/defineTool.d.ts.map +1 -0
  189. package/lib/typescript/module/ui/components/ChangeRow.d.ts +52 -0
  190. package/lib/typescript/module/ui/components/ChangeRow.d.ts.map +1 -0
  191. package/lib/typescript/module/ui/components/ChipStrip.d.ts +41 -0
  192. package/lib/typescript/module/ui/components/ChipStrip.d.ts.map +1 -0
  193. package/lib/typescript/module/ui/components/DetailViewToggle.d.ts +36 -0
  194. package/lib/typescript/module/ui/components/DetailViewToggle.d.ts.map +1 -0
  195. package/lib/typescript/module/ui/components/DevToolsCard.d.ts +8 -1
  196. package/lib/typescript/module/ui/components/DevToolsCard.d.ts.map +1 -1
  197. package/lib/typescript/module/ui/components/EmptyState.d.ts +14 -1
  198. package/lib/typescript/module/ui/components/EmptyState.d.ts.map +1 -1
  199. package/lib/typescript/module/ui/components/EntityFilterView.d.ts +51 -0
  200. package/lib/typescript/module/ui/components/EntityFilterView.d.ts.map +1 -0
  201. package/lib/typescript/module/ui/components/ExportPreview.d.ts +48 -0
  202. package/lib/typescript/module/ui/components/ExportPreview.d.ts.map +1 -0
  203. package/lib/typescript/module/ui/components/InfoRow.d.ts +33 -0
  204. package/lib/typescript/module/ui/components/InfoRow.d.ts.map +1 -0
  205. package/lib/typescript/module/ui/components/ModalHeader.d.ts +31 -1
  206. package/lib/typescript/module/ui/components/ModalHeader.d.ts.map +1 -1
  207. package/lib/typescript/module/ui/components/Pill.d.ts +38 -0
  208. package/lib/typescript/module/ui/components/Pill.d.ts.map +1 -0
  209. package/lib/typescript/module/ui/components/ToggleRow.d.ts +33 -0
  210. package/lib/typescript/module/ui/components/ToggleRow.d.ts.map +1 -0
  211. package/lib/typescript/module/ui/components/ToolEmptyState.d.ts +113 -0
  212. package/lib/typescript/module/ui/components/ToolEmptyState.d.ts.map +1 -0
  213. package/lib/typescript/module/ui/components/ToolFooter.d.ts +69 -0
  214. package/lib/typescript/module/ui/components/ToolFooter.d.ts.map +1 -0
  215. package/lib/typescript/module/ui/components/WindowControls.d.ts +7 -1
  216. package/lib/typescript/module/ui/components/WindowControls.d.ts.map +1 -1
  217. package/lib/typescript/module/ui/components/index.d.ts +11 -0
  218. package/lib/typescript/module/ui/components/index.d.ts.map +1 -1
  219. package/lib/typescript/module/ui/index.d.ts +2 -0
  220. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  221. package/lib/typescript/module/ui/listPresets.d.ts +28 -0
  222. package/lib/typescript/module/ui/listPresets.d.ts.map +1 -0
  223. package/lib/typescript/module/ui/night/primitives.d.ts +3 -1
  224. package/lib/typescript/module/ui/night/primitives.d.ts.map +1 -1
  225. package/lib/typescript/module/ui/otto/OttoSprite.d.ts +103 -0
  226. package/lib/typescript/module/ui/otto/OttoSprite.d.ts.map +1 -0
  227. package/lib/typescript/module/ui/otto/index.d.ts +19 -0
  228. package/lib/typescript/module/ui/otto/index.d.ts.map +1 -0
  229. package/lib/typescript/module/ui/otto/ottoEngine.d.ts +2205 -0
  230. package/lib/typescript/module/ui/otto/ottoEngine.d.ts.map +1 -0
  231. package/lib/typescript/module/ui/otto/ottoSheet.d.ts +73 -0
  232. package/lib/typescript/module/ui/otto/ottoSheet.d.ts.map +1 -0
  233. package/lib/typescript/module/utils/snapshotProviderKit.d.ts +81 -0
  234. package/lib/typescript/module/utils/snapshotProviderKit.d.ts.map +1 -0
  235. package/lib/typescript/module/utils/stateTools.d.ts +44 -0
  236. package/lib/typescript/module/utils/stateTools.d.ts.map +1 -0
  237. 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,149 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * The one "nothing here" panel, for every tool that shows a list.
5
+ *
6
+ * WHY THIS EXISTS
7
+ *
8
+ * Every capture tool — network, events, highlight-updates, storage, zustand,
9
+ * redux, jotai, console — renders the same panel with the same four causes and
10
+ * different nouns. Written out per tool, that produced four copies of the same
11
+ * layout (each of which had to be re-inset by hand the first time a sentence
12
+ * was longer than "No events yet"), and four independent guesses at the
13
+ * PRECEDENCE between those causes. The guesses disagreed, and the disagreements
14
+ * were bugs:
15
+ *
16
+ * - A search that matched nothing showed "Enable tracking to start
17
+ * capturing" — pointing at a toggle that was already on.
18
+ * - Turning every source chip off showed "Events will appear here as they
19
+ * occur" — inviting you to go generate events that were already in the
20
+ * store, behind your own filter.
21
+ * - Typing into a search box while the store was empty produced no
22
+ * acknowledgement of the query at all, which reads as a dead search box.
23
+ *
24
+ * So the precedence lives here, once, and each tool supplies only what is
25
+ * genuinely its own: the noun, and what "switched on but waiting" looks like
26
+ * for it (network fishes, events listens, the highlighter stares).
27
+ *
28
+ * SPLIT IN TWO ON PURPOSE
29
+ *
30
+ * `resolveListEmptyState` is a pure function returning `{ otto, title,
31
+ * message }`, and `ToolEmptyState` renders that object. Tools with a cause
32
+ * nobody else has — storage's "no issues found" (which is a PASS, not a
33
+ * failure), zustand's unregistered store — resolve the common cases and
34
+ * substitute their own, or skip the resolver and hand the shell a literal.
35
+ * Adding a mascot to every tool at once is then one edit in this file, which is
36
+ * also what makes the Flutter and Swift ports one component to mirror instead
37
+ * of eight.
38
+ */
39
+
40
+ import { StyleSheet, Text, View } from "react-native";
41
+ import { Otto } from "../otto/index.js";
42
+ import { night } from "../night/nightTheme.js";
43
+
44
+ /** What a "nothing here" panel says. */
45
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
46
+ /**
47
+ * The panel itself: Otto, a heading, a sentence. Nothing else — this only ever
48
+ * renders where the alternative is a blank body, so it has no actions and no
49
+ * decoration to compete with the list it stands in for.
50
+ */
51
+ export function ToolEmptyState({
52
+ otto,
53
+ title,
54
+ message,
55
+ testID,
56
+ style
57
+ }) {
58
+ return /*#__PURE__*/_jsxs(View, {
59
+ style: [styles.container, style],
60
+ testID: testID,
61
+ children: [/*#__PURE__*/_jsx(Otto, {
62
+ state: otto,
63
+ pixelSize: 2
64
+ }), /*#__PURE__*/_jsx(Text, {
65
+ style: styles.title,
66
+ testID: testID ? `${testID}-title` : undefined,
67
+ numberOfLines: 2,
68
+ children: title
69
+ }), /*#__PURE__*/_jsx(Text, {
70
+ style: styles.message,
71
+ testID: testID ? `${testID}-text` : undefined,
72
+ children: message
73
+ })]
74
+ });
75
+ }
76
+ /**
77
+ * Which "nothing here" this is, in the order the facts answer the question.
78
+ *
79
+ * A typed query first (see `search`), then the user's filters, then the
80
+ * capture switch, then the honest "nothing yet".
81
+ */
82
+ export function resolveListEmptyState(facts) {
83
+ const {
84
+ subject,
85
+ verb = "captured",
86
+ search,
87
+ total = 0,
88
+ capturing,
89
+ waiting,
90
+ paused,
91
+ blocked
92
+ } = facts;
93
+ const term = (search ?? "").trim();
94
+ if (term) {
95
+ return {
96
+ otto: "sad",
97
+ // The query goes in the HEADING because checking what you typed is the
98
+ // first thing you do; the body names whichever blocker is in the way.
99
+ title: `No results for “${term}”`,
100
+ message: blocked ?? (total > 0 ? `None of the ${total} ${verb} ${subject} match. Clear the search to see them.` : capturing === false ? `Nothing is ${verb} to search — capture is off. Turn it on to start.` : `Nothing has been ${verb} yet, so there is nothing to match.`)
101
+ };
102
+ }
103
+ if (blocked) {
104
+ return {
105
+ otto: "filtering",
106
+ title: "Filtered Out",
107
+ message: blocked
108
+ };
109
+ }
110
+ if (total > 0) {
111
+ return {
112
+ otto: "filtering",
113
+ title: "Filtered Out",
114
+ message: `${total} ${verb} ${subject} ${total === 1 ? "is" : "are"} hidden by the active filters.`
115
+ };
116
+ }
117
+ if (capturing === false) {
118
+ return {
119
+ otto: paused?.otto ?? "paused",
120
+ title: paused?.title ?? "Not capturing",
121
+ message: paused?.message ?? "Capture is off. Turn it on to start."
122
+ };
123
+ }
124
+ return waiting;
125
+ }
126
+ const styles = StyleSheet.create({
127
+ container: {
128
+ alignItems: "center",
129
+ paddingVertical: 40,
130
+ // The generated sentences are full sentences. Every tool that hand-rolled
131
+ // this panel shipped without an inset and had it run to both edges of the
132
+ // sheet the first time the copy grew past a few words.
133
+ paddingHorizontal: 24
134
+ },
135
+ title: {
136
+ color: night.color.text,
137
+ fontSize: 14,
138
+ fontWeight: "600",
139
+ marginTop: 12,
140
+ marginBottom: 6,
141
+ textAlign: "center"
142
+ },
143
+ message: {
144
+ color: night.color.textTertiary,
145
+ fontSize: 12,
146
+ textAlign: "center",
147
+ lineHeight: 17
148
+ }
149
+ });
@@ -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
+ });
@@ -70,7 +70,8 @@ export function WindowControls({
70
70
  onMinimize,
71
71
  onToggleMode,
72
72
  mode,
73
- variant = "night"
73
+ variant = "night",
74
+ defaultExpanded
74
75
  }) {
75
76
  // Show action-based icon: what will happen when clicked
76
77
  const ToggleModeIcon = mode === "floating" ? DockBottom : FloatWindow;
@@ -125,7 +126,8 @@ export function WindowControls({
125
126
  onMinimize: onMinimize,
126
127
  onToggleMode: onToggleMode,
127
128
  mode: mode,
128
- variant: variant
129
+ variant: variant,
130
+ defaultExpanded: defaultExpanded
129
131
  });
130
132
  }
131
133
  function ExpandableWindowControls({
@@ -133,11 +135,12 @@ function ExpandableWindowControls({
133
135
  onMinimize,
134
136
  onToggleMode,
135
137
  mode,
136
- variant = "night"
138
+ variant = "night",
139
+ defaultExpanded = false
137
140
  }) {
138
141
  const isNight = variant === "night";
139
- const [expanded, setExpanded] = useState(false);
140
- const expandAnim = useRef(new Animated.Value(0)).current;
142
+ const [expanded, setExpanded] = useState(defaultExpanded);
143
+ const expandAnim = useRef(new Animated.Value(defaultExpanded ? 1 : 0)).current;
141
144
  const dismissTimeout = useRef(null);
142
145
  const ToggleModeIcon = mode === "floating" ? DockBottom : FloatWindow;
143
146
  const toggleModeLabel = mode === "floating" ? "Dock to bottom sheet" : "Make floating window";
@@ -21,6 +21,9 @@ export { CompactRow } from "./CompactRow.js";
21
21
  export { DevToolsCard, DEVTOOLS_CARD_CONSTANTS } from "./DevToolsCard.js";
22
22
  export { HeaderSearchButton } from "./HeaderSearchButton.js";
23
23
  export { EmptyState, NoDataEmptyState, NoResultsEmptyState, NoSearchResultsEmptyState } from "./EmptyState.js";
24
+ // The shared "nothing here" panel + the precedence between its causes. Every
25
+ // capture tool's list empty goes through this — see the file header.
26
+ export { ToolEmptyState, resolveListEmptyState } from "./ToolEmptyState.js";
24
27
  export { StatusIndicator } from "./StatusIndicator.js";
25
28
  export { TimeDisplay } from "./TimeDisplay.js";
26
29
  export { DetailView } from "./DetailView.js";
@@ -37,4 +40,13 @@ export { PowerToggleButton } from "./PowerToggleButton.js";
37
40
  export { ExpandedInfoRow, PillBadge } from "./ExpandedInfoRow.js";
38
41
 
39
42
  // EventHistoryViewer components
40
- 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";
@@ -15,4 +15,10 @@ export { toolTheme } from "./toolTheme.js";
15
15
  export { CyberpunkSectionButton } from "./console/CyberpunkSectionButton.js";
16
16
 
17
17
  // Game UI (colors, hooks, components)
18
- export * from "./gameUI/index.js";
18
+ export * from "./gameUI/index.js";
19
+
20
+ // Otto — the Buoy mascot (see OTTO_PLACEMENT_PLAN.md for where he belongs)
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],