@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.
Files changed (189) hide show
  1. package/lib/commonjs/JsModal.js +57 -22
  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/index.js +8 -1
  10. package/lib/commonjs/stores/ChangeLog.js +197 -0
  11. package/lib/commonjs/stores/createToolStore.js +175 -0
  12. package/lib/commonjs/stores/index.js +15 -1
  13. package/lib/commonjs/sync/toolSyncAdapter.js +63 -0
  14. package/lib/commonjs/sync/wireForm.js +172 -0
  15. package/lib/commonjs/tools/defineTool.js +79 -0
  16. package/lib/commonjs/ui/components/ChangeRow.js +110 -0
  17. package/lib/commonjs/ui/components/ChipStrip.js +94 -0
  18. package/lib/commonjs/ui/components/DetailViewToggle.js +130 -0
  19. package/lib/commonjs/ui/components/DevToolsCard.js +3 -1
  20. package/lib/commonjs/ui/components/EntityFilterView.js +354 -0
  21. package/lib/commonjs/ui/components/ExportPreview.js +174 -0
  22. package/lib/commonjs/ui/components/InfoRow.js +90 -0
  23. package/lib/commonjs/ui/components/ModalHeader.js +40 -7
  24. package/lib/commonjs/ui/components/Pill.js +114 -0
  25. package/lib/commonjs/ui/components/ToggleRow.js +116 -0
  26. package/lib/commonjs/ui/components/ToolFooter.js +204 -0
  27. package/lib/commonjs/ui/components/index.js +100 -1
  28. package/lib/commonjs/ui/index.js +24 -2
  29. package/lib/commonjs/ui/listPresets.js +43 -0
  30. package/lib/commonjs/ui/night/primitives.js +3 -1
  31. package/lib/commonjs/utils/snapshotProviderKit.js +167 -0
  32. package/lib/commonjs/utils/stateTools.js +160 -0
  33. package/lib/module/JsModal.js +57 -22
  34. package/lib/module/hooks/index.js +3 -1
  35. package/lib/module/hooks/safe-area-impl.js +1 -1
  36. package/lib/module/hooks/useChangeLog.js +50 -0
  37. package/lib/module/hooks/useEventStoreEvents.js +61 -0
  38. package/lib/module/hooks/usePersistedState.js +44 -10
  39. package/lib/module/index.js +11 -1
  40. package/lib/module/storage/definePersistedSetting.js +63 -0
  41. package/lib/module/storage/index.js +2 -1
  42. package/lib/module/stores/ChangeLog.js +192 -0
  43. package/lib/module/stores/createToolStore.js +171 -0
  44. package/lib/module/stores/index.js +3 -1
  45. package/lib/module/sync/toolSyncAdapter.js +58 -0
  46. package/lib/module/sync/wireForm.js +159 -0
  47. package/lib/module/tools/defineTool.js +74 -0
  48. package/lib/module/ui/components/ChangeRow.js +105 -0
  49. package/lib/module/ui/components/ChipStrip.js +91 -0
  50. package/lib/module/ui/components/DetailViewToggle.js +125 -0
  51. package/lib/module/ui/components/DevToolsCard.js +3 -1
  52. package/lib/module/ui/components/EntityFilterView.js +350 -0
  53. package/lib/module/ui/components/ExportPreview.js +169 -0
  54. package/lib/module/ui/components/InfoRow.js +86 -0
  55. package/lib/module/ui/components/ModalHeader.js +40 -7
  56. package/lib/module/ui/components/Pill.js +110 -0
  57. package/lib/module/ui/components/ToggleRow.js +112 -0
  58. package/lib/module/ui/components/ToolFooter.js +196 -0
  59. package/lib/module/ui/components/index.js +10 -1
  60. package/lib/module/ui/index.js +4 -1
  61. package/lib/module/ui/listPresets.js +39 -0
  62. package/lib/module/ui/night/primitives.js +3 -1
  63. package/lib/module/utils/snapshotProviderKit.js +156 -0
  64. package/lib/module/utils/stateTools.js +154 -0
  65. package/lib/typescript/commonjs/JsModal.d.ts.map +1 -1
  66. package/lib/typescript/commonjs/hooks/index.d.ts +3 -1
  67. package/lib/typescript/commonjs/hooks/index.d.ts.map +1 -1
  68. package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
  69. package/lib/typescript/commonjs/hooks/useChangeLog.d.ts +38 -0
  70. package/lib/typescript/commonjs/hooks/useChangeLog.d.ts.map +1 -0
  71. package/lib/typescript/commonjs/hooks/useEventStoreEvents.d.ts +25 -0
  72. package/lib/typescript/commonjs/hooks/useEventStoreEvents.d.ts.map +1 -0
  73. package/lib/typescript/commonjs/hooks/usePersistedState.d.ts +34 -5
  74. package/lib/typescript/commonjs/hooks/usePersistedState.d.ts.map +1 -1
  75. package/lib/typescript/commonjs/index.d.ts +6 -1
  76. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  77. package/lib/typescript/commonjs/storage/definePersistedSetting.d.ts +39 -0
  78. package/lib/typescript/commonjs/storage/definePersistedSetting.d.ts.map +1 -0
  79. package/lib/typescript/commonjs/storage/index.d.ts +1 -0
  80. package/lib/typescript/commonjs/storage/index.d.ts.map +1 -1
  81. package/lib/typescript/commonjs/stores/ChangeLog.d.ts +100 -0
  82. package/lib/typescript/commonjs/stores/ChangeLog.d.ts.map +1 -0
  83. package/lib/typescript/commonjs/stores/createToolStore.d.ts +92 -0
  84. package/lib/typescript/commonjs/stores/createToolStore.d.ts.map +1 -0
  85. package/lib/typescript/commonjs/stores/index.d.ts +2 -0
  86. package/lib/typescript/commonjs/stores/index.d.ts.map +1 -1
  87. package/lib/typescript/commonjs/sync/toolSyncAdapter.d.ts +66 -0
  88. package/lib/typescript/commonjs/sync/toolSyncAdapter.d.ts.map +1 -0
  89. package/lib/typescript/commonjs/sync/wireForm.d.ts +100 -0
  90. package/lib/typescript/commonjs/sync/wireForm.d.ts.map +1 -0
  91. package/lib/typescript/commonjs/tools/defineTool.d.ts +100 -0
  92. package/lib/typescript/commonjs/tools/defineTool.d.ts.map +1 -0
  93. package/lib/typescript/commonjs/ui/components/ChangeRow.d.ts +52 -0
  94. package/lib/typescript/commonjs/ui/components/ChangeRow.d.ts.map +1 -0
  95. package/lib/typescript/commonjs/ui/components/ChipStrip.d.ts +41 -0
  96. package/lib/typescript/commonjs/ui/components/ChipStrip.d.ts.map +1 -0
  97. package/lib/typescript/commonjs/ui/components/DetailViewToggle.d.ts +36 -0
  98. package/lib/typescript/commonjs/ui/components/DetailViewToggle.d.ts.map +1 -0
  99. package/lib/typescript/commonjs/ui/components/DevToolsCard.d.ts +8 -1
  100. package/lib/typescript/commonjs/ui/components/DevToolsCard.d.ts.map +1 -1
  101. package/lib/typescript/commonjs/ui/components/EntityFilterView.d.ts +51 -0
  102. package/lib/typescript/commonjs/ui/components/EntityFilterView.d.ts.map +1 -0
  103. package/lib/typescript/commonjs/ui/components/ExportPreview.d.ts +48 -0
  104. package/lib/typescript/commonjs/ui/components/ExportPreview.d.ts.map +1 -0
  105. package/lib/typescript/commonjs/ui/components/InfoRow.d.ts +33 -0
  106. package/lib/typescript/commonjs/ui/components/InfoRow.d.ts.map +1 -0
  107. package/lib/typescript/commonjs/ui/components/ModalHeader.d.ts +31 -1
  108. package/lib/typescript/commonjs/ui/components/ModalHeader.d.ts.map +1 -1
  109. package/lib/typescript/commonjs/ui/components/Pill.d.ts +38 -0
  110. package/lib/typescript/commonjs/ui/components/Pill.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/ui/components/ToggleRow.d.ts +33 -0
  112. package/lib/typescript/commonjs/ui/components/ToggleRow.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/ui/components/ToolFooter.d.ts +69 -0
  114. package/lib/typescript/commonjs/ui/components/ToolFooter.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/ui/components/index.d.ts +9 -0
  116. package/lib/typescript/commonjs/ui/components/index.d.ts.map +1 -1
  117. package/lib/typescript/commonjs/ui/index.d.ts +1 -0
  118. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  119. package/lib/typescript/commonjs/ui/listPresets.d.ts +28 -0
  120. package/lib/typescript/commonjs/ui/listPresets.d.ts.map +1 -0
  121. package/lib/typescript/commonjs/ui/night/primitives.d.ts +3 -1
  122. package/lib/typescript/commonjs/ui/night/primitives.d.ts.map +1 -1
  123. package/lib/typescript/commonjs/utils/snapshotProviderKit.d.ts +81 -0
  124. package/lib/typescript/commonjs/utils/snapshotProviderKit.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/utils/stateTools.d.ts +44 -0
  126. package/lib/typescript/commonjs/utils/stateTools.d.ts.map +1 -0
  127. package/lib/typescript/module/JsModal.d.ts.map +1 -1
  128. package/lib/typescript/module/hooks/index.d.ts +3 -1
  129. package/lib/typescript/module/hooks/index.d.ts.map +1 -1
  130. package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
  131. package/lib/typescript/module/hooks/useChangeLog.d.ts +38 -0
  132. package/lib/typescript/module/hooks/useChangeLog.d.ts.map +1 -0
  133. package/lib/typescript/module/hooks/useEventStoreEvents.d.ts +25 -0
  134. package/lib/typescript/module/hooks/useEventStoreEvents.d.ts.map +1 -0
  135. package/lib/typescript/module/hooks/usePersistedState.d.ts +34 -5
  136. package/lib/typescript/module/hooks/usePersistedState.d.ts.map +1 -1
  137. package/lib/typescript/module/index.d.ts +6 -1
  138. package/lib/typescript/module/index.d.ts.map +1 -1
  139. package/lib/typescript/module/storage/definePersistedSetting.d.ts +39 -0
  140. package/lib/typescript/module/storage/definePersistedSetting.d.ts.map +1 -0
  141. package/lib/typescript/module/storage/index.d.ts +1 -0
  142. package/lib/typescript/module/storage/index.d.ts.map +1 -1
  143. package/lib/typescript/module/stores/ChangeLog.d.ts +100 -0
  144. package/lib/typescript/module/stores/ChangeLog.d.ts.map +1 -0
  145. package/lib/typescript/module/stores/createToolStore.d.ts +92 -0
  146. package/lib/typescript/module/stores/createToolStore.d.ts.map +1 -0
  147. package/lib/typescript/module/stores/index.d.ts +2 -0
  148. package/lib/typescript/module/stores/index.d.ts.map +1 -1
  149. package/lib/typescript/module/sync/toolSyncAdapter.d.ts +66 -0
  150. package/lib/typescript/module/sync/toolSyncAdapter.d.ts.map +1 -0
  151. package/lib/typescript/module/sync/wireForm.d.ts +100 -0
  152. package/lib/typescript/module/sync/wireForm.d.ts.map +1 -0
  153. package/lib/typescript/module/tools/defineTool.d.ts +100 -0
  154. package/lib/typescript/module/tools/defineTool.d.ts.map +1 -0
  155. package/lib/typescript/module/ui/components/ChangeRow.d.ts +52 -0
  156. package/lib/typescript/module/ui/components/ChangeRow.d.ts.map +1 -0
  157. package/lib/typescript/module/ui/components/ChipStrip.d.ts +41 -0
  158. package/lib/typescript/module/ui/components/ChipStrip.d.ts.map +1 -0
  159. package/lib/typescript/module/ui/components/DetailViewToggle.d.ts +36 -0
  160. package/lib/typescript/module/ui/components/DetailViewToggle.d.ts.map +1 -0
  161. package/lib/typescript/module/ui/components/DevToolsCard.d.ts +8 -1
  162. package/lib/typescript/module/ui/components/DevToolsCard.d.ts.map +1 -1
  163. package/lib/typescript/module/ui/components/EntityFilterView.d.ts +51 -0
  164. package/lib/typescript/module/ui/components/EntityFilterView.d.ts.map +1 -0
  165. package/lib/typescript/module/ui/components/ExportPreview.d.ts +48 -0
  166. package/lib/typescript/module/ui/components/ExportPreview.d.ts.map +1 -0
  167. package/lib/typescript/module/ui/components/InfoRow.d.ts +33 -0
  168. package/lib/typescript/module/ui/components/InfoRow.d.ts.map +1 -0
  169. package/lib/typescript/module/ui/components/ModalHeader.d.ts +31 -1
  170. package/lib/typescript/module/ui/components/ModalHeader.d.ts.map +1 -1
  171. package/lib/typescript/module/ui/components/Pill.d.ts +38 -0
  172. package/lib/typescript/module/ui/components/Pill.d.ts.map +1 -0
  173. package/lib/typescript/module/ui/components/ToggleRow.d.ts +33 -0
  174. package/lib/typescript/module/ui/components/ToggleRow.d.ts.map +1 -0
  175. package/lib/typescript/module/ui/components/ToolFooter.d.ts +69 -0
  176. package/lib/typescript/module/ui/components/ToolFooter.d.ts.map +1 -0
  177. package/lib/typescript/module/ui/components/index.d.ts +9 -0
  178. package/lib/typescript/module/ui/components/index.d.ts.map +1 -1
  179. package/lib/typescript/module/ui/index.d.ts +1 -0
  180. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  181. package/lib/typescript/module/ui/listPresets.d.ts +28 -0
  182. package/lib/typescript/module/ui/listPresets.d.ts.map +1 -0
  183. package/lib/typescript/module/ui/night/primitives.d.ts +3 -1
  184. package/lib/typescript/module/ui/night/primitives.d.ts.map +1 -1
  185. package/lib/typescript/module/utils/snapshotProviderKit.d.ts +81 -0
  186. package/lib/typescript/module/utils/snapshotProviderKit.d.ts.map +1 -0
  187. package/lib/typescript/module/utils/stateTools.d.ts +44 -0
  188. package/lib/typescript/module/utils/stateTools.d.ts.map +1 -0
  189. package/package.json +4 -4
@@ -0,0 +1,350 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * EntityFilterView — the "hide these by name" filter screen the state tools
5
+ * share: a list of registered entities (stores, atoms) you can tap to hide,
6
+ * the active name patterns with a remove ✕, an add-pattern affordance, and
7
+ * a how-it-works card.
8
+ *
9
+ * zustand and jotai each shipped their own copy (~370 lines apiece). The
10
+ * tool supplies the entities, the nouns and the testID prefix; the screen
11
+ * is drawn once.
12
+ *
13
+ * testID convention (unchanged from zustand's):
14
+ * `${prefix}-filters-scroll`, `${prefix}-filters-${entityKey}-count`,
15
+ * `${prefix}-filters-${entityKey}-${slug(name)}`, `${prefix}-filters-count`,
16
+ * `${prefix}-filters-add-open`, `${prefix}-filters-add-input`,
17
+ * `${prefix}-filters-chip-${slug(pattern)}`.
18
+ */
19
+
20
+ import { useState } from "react";
21
+ import { ScrollView, StyleSheet, Text, TouchableOpacity, View } from "react-native";
22
+ import { Filter, X } from "../../icons/index.js";
23
+ import { night } from "../night/nightTheme.js";
24
+ import { SectionHeader } from "./SectionHeader.js";
25
+ import { AddFilterButton, AddFilterInput } from "./FilterComponents.js";
26
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
27
+ /** True if any active pattern hides this entity. */
28
+ function isHidden(entity, ignoredPatterns) {
29
+ return Array.from(ignoredPatterns).some(p => entity.name.toLowerCase().includes(p.toLowerCase()));
30
+ }
31
+
32
+ /** The entity color for a pattern that exactly names a registered entity. */
33
+ function colorForPattern(pattern, entities) {
34
+ const match = entities.find(e => e.name.toLowerCase() === pattern.toLowerCase());
35
+ return match ? match.color : null;
36
+ }
37
+ export function EntityFilterView({
38
+ entities,
39
+ ignoredPatterns,
40
+ onTogglePattern,
41
+ onAddPattern,
42
+ entityNoun,
43
+ entitySingular,
44
+ entityKey,
45
+ testIDPrefix,
46
+ slug,
47
+ howItWorks,
48
+ examples,
49
+ addPlaceholder,
50
+ emptyMessage
51
+ }) {
52
+ const [showAddInput, setShowAddInput] = useState(false);
53
+ const [inputValue, setInputValue] = useState("");
54
+ const handleAddPattern = () => {
55
+ const trimmed = inputValue.trim();
56
+ if (trimmed) {
57
+ onAddPattern(trimmed);
58
+ setInputValue("");
59
+ setShowAddInput(false);
60
+ }
61
+ };
62
+ return /*#__PURE__*/_jsxs(ScrollView, {
63
+ style: styles.container,
64
+ contentContainerStyle: styles.scrollContent,
65
+ showsVerticalScrollIndicator: false,
66
+ nestedScrollEnabled: true,
67
+ testID: `${testIDPrefix}-filters-scroll`,
68
+ children: [entities.length === 0 && emptyMessage ? /*#__PURE__*/_jsxs(View, {
69
+ style: styles.section,
70
+ children: [/*#__PURE__*/_jsx(SectionHeader, {
71
+ children: /*#__PURE__*/_jsxs(SectionHeader.Title, {
72
+ children: ["REGISTERED ", entityNoun]
73
+ })
74
+ }), /*#__PURE__*/_jsx(Text, {
75
+ style: styles.emptyText,
76
+ testID: `${testIDPrefix}-filters-${entityKey}s-empty`,
77
+ children: emptyMessage
78
+ })]
79
+ }) : null, entities.length > 0 && /*#__PURE__*/_jsxs(View, {
80
+ style: styles.section,
81
+ children: [/*#__PURE__*/_jsxs(SectionHeader, {
82
+ children: [/*#__PURE__*/_jsxs(SectionHeader.Title, {
83
+ children: ["REGISTERED ", entityNoun]
84
+ }), /*#__PURE__*/_jsx(SectionHeader.Badge, {
85
+ count: entities.length,
86
+ color: night.color.accent,
87
+ testID: `${testIDPrefix}-filters-${entityKey}-count`
88
+ })]
89
+ }), /*#__PURE__*/_jsx(ScrollView, {
90
+ style: styles.entityList,
91
+ contentContainerStyle: styles.entityListContent,
92
+ showsVerticalScrollIndicator: true,
93
+ nestedScrollEnabled: true,
94
+ testID: `${testIDPrefix}-filters-${entityKey}-list`,
95
+ children: entities.map(entity => {
96
+ const hidden = isHidden(entity, ignoredPatterns);
97
+ return /*#__PURE__*/_jsxs(TouchableOpacity, {
98
+ style: [styles.entityRow, hidden && styles.entityRowHidden],
99
+ onPress: () => onAddPattern(entity.name),
100
+ disabled: hidden,
101
+ testID: `${testIDPrefix}-filters-${entityKey}-${slug(entity.name)}`,
102
+ accessibilityRole: "button",
103
+ accessibilityLabel: `Hide ${entity.name}`,
104
+ accessibilityState: {
105
+ disabled: hidden
106
+ },
107
+ children: [/*#__PURE__*/_jsx(View, {
108
+ style: [styles.dot, {
109
+ backgroundColor: hidden ? night.color.textTertiary : entity.color
110
+ }]
111
+ }), /*#__PURE__*/_jsx(Text, {
112
+ style: [styles.entityText, hidden ? styles.entityTextHidden : {
113
+ color: entity.color
114
+ }],
115
+ numberOfLines: 1,
116
+ children: entity.name
117
+ }), hidden ? /*#__PURE__*/_jsx(Text, {
118
+ style: styles.hiddenLabel,
119
+ children: "hidden"
120
+ }) : /*#__PURE__*/_jsx(Text, {
121
+ style: [styles.addLabel, {
122
+ color: entity.color + "99"
123
+ }],
124
+ children: "+ hide"
125
+ })]
126
+ }, entity.name);
127
+ })
128
+ })]
129
+ }), /*#__PURE__*/_jsxs(View, {
130
+ style: styles.section,
131
+ children: [/*#__PURE__*/_jsxs(SectionHeader, {
132
+ children: [/*#__PURE__*/_jsx(SectionHeader.Icon, {
133
+ icon: Filter,
134
+ color: night.color.accent,
135
+ size: 12
136
+ }), /*#__PURE__*/_jsxs(SectionHeader.Title, {
137
+ children: [entitySingular.toUpperCase(), " NAME FILTERS"]
138
+ }), ignoredPatterns.size > 0 && /*#__PURE__*/_jsx(SectionHeader.Badge, {
139
+ count: ignoredPatterns.size,
140
+ color: night.color.accent,
141
+ testID: `${testIDPrefix}-filters-count`
142
+ })]
143
+ }), /*#__PURE__*/_jsx(View, {
144
+ style: styles.addInputWrapper,
145
+ children: !showAddInput ? /*#__PURE__*/_jsx(AddFilterButton, {
146
+ onPress: () => setShowAddInput(true),
147
+ color: night.color.accent,
148
+ label: `Add ${entitySingular} name pattern`,
149
+ testID: `${testIDPrefix}-filters-add-open`
150
+ }) : /*#__PURE__*/_jsx(AddFilterInput, {
151
+ value: inputValue,
152
+ onChange: setInputValue,
153
+ onSubmit: handleAddPattern,
154
+ onCancel: () => {
155
+ setShowAddInput(false);
156
+ setInputValue("");
157
+ },
158
+ placeholder: addPlaceholder ?? `Enter ${entitySingular} name pattern to hide...`,
159
+ color: night.color.accent,
160
+ testID: `${testIDPrefix}-filters-add-input`
161
+ })
162
+ }), ignoredPatterns.size > 0 && /*#__PURE__*/_jsx(View, {
163
+ style: styles.patternList,
164
+ children: Array.from(ignoredPatterns).map(pattern => {
165
+ const color = colorForPattern(pattern, entities);
166
+ return /*#__PURE__*/_jsxs(TouchableOpacity, {
167
+ style: styles.patternRow,
168
+ onPress: () => onTogglePattern(pattern),
169
+ activeOpacity: 0.8,
170
+ testID: `${testIDPrefix}-filters-chip-${slug(pattern)}`,
171
+ accessibilityRole: "button",
172
+ accessibilityLabel: `Remove filter ${pattern}`,
173
+ children: [color ? /*#__PURE__*/_jsx(View, {
174
+ style: [styles.dot, {
175
+ backgroundColor: color
176
+ }]
177
+ }) : null, /*#__PURE__*/_jsx(Text, {
178
+ style: [styles.patternText, color ? {
179
+ color
180
+ } : null],
181
+ numberOfLines: 1,
182
+ children: pattern
183
+ }), /*#__PURE__*/_jsx(X, {
184
+ size: 12,
185
+ color: night.color.accent + "80"
186
+ })]
187
+ }, pattern);
188
+ })
189
+ })]
190
+ }), /*#__PURE__*/_jsxs(View, {
191
+ style: styles.section,
192
+ children: [/*#__PURE__*/_jsxs(SectionHeader, {
193
+ children: [/*#__PURE__*/_jsx(SectionHeader.Icon, {
194
+ icon: Filter,
195
+ color: night.color.textSecondary,
196
+ size: 12
197
+ }), /*#__PURE__*/_jsx(SectionHeader.Title, {
198
+ children: "HOW EVENT FILTERS WORK"
199
+ })]
200
+ }), /*#__PURE__*/_jsx(Text, {
201
+ style: styles.howItWorksText,
202
+ children: howItWorks
203
+ }), /*#__PURE__*/_jsxs(View, {
204
+ style: styles.examplesContainer,
205
+ children: [/*#__PURE__*/_jsx(Text, {
206
+ style: styles.examplesTitle,
207
+ children: "EXAMPLES:"
208
+ }), examples.map(ex => /*#__PURE__*/_jsx(Text, {
209
+ style: styles.exampleItem,
210
+ children: ex
211
+ }, ex))]
212
+ })]
213
+ })]
214
+ });
215
+ }
216
+ const styles = StyleSheet.create({
217
+ container: {
218
+ flex: 1,
219
+ // Transparent so the night sheet's star field shows through.
220
+ backgroundColor: "transparent"
221
+ },
222
+ scrollContent: {
223
+ paddingTop: 16,
224
+ paddingHorizontal: 16,
225
+ paddingBottom: 24,
226
+ gap: 16
227
+ },
228
+ section: {
229
+ backgroundColor: night.color.surface,
230
+ borderRadius: 16,
231
+ borderWidth: 1,
232
+ borderColor: night.color.border,
233
+ overflow: "hidden"
234
+ },
235
+ entityList: {
236
+ maxHeight: 180
237
+ },
238
+ entityListContent: {
239
+ paddingHorizontal: 16,
240
+ paddingTop: 8,
241
+ paddingBottom: 16,
242
+ gap: 10
243
+ },
244
+ entityRow: {
245
+ flexDirection: "row",
246
+ alignItems: "center",
247
+ gap: 10,
248
+ paddingVertical: 10,
249
+ paddingHorizontal: 12,
250
+ backgroundColor: night.color.surfaceElevated,
251
+ borderRadius: 8,
252
+ borderWidth: 1,
253
+ borderColor: night.color.border
254
+ },
255
+ entityRowHidden: {
256
+ opacity: 0.45
257
+ },
258
+ dot: {
259
+ width: 7,
260
+ height: 7,
261
+ borderRadius: 3.5
262
+ },
263
+ entityText: {
264
+ flex: 1,
265
+ fontSize: 12,
266
+ fontWeight: "600",
267
+ fontFamily: "monospace"
268
+ },
269
+ entityTextHidden: {
270
+ color: night.color.textTertiary,
271
+ textDecorationLine: "line-through"
272
+ },
273
+ hiddenLabel: {
274
+ fontSize: 10,
275
+ fontWeight: "500",
276
+ color: night.color.textTertiary,
277
+ fontFamily: "monospace"
278
+ },
279
+ addLabel: {
280
+ fontSize: 10,
281
+ fontWeight: "600",
282
+ fontFamily: "monospace"
283
+ },
284
+ addInputWrapper: {
285
+ paddingHorizontal: 16,
286
+ paddingTop: 8,
287
+ paddingBottom: 8
288
+ },
289
+ patternList: {
290
+ paddingHorizontal: 16,
291
+ paddingBottom: 16,
292
+ gap: 8
293
+ },
294
+ patternRow: {
295
+ flexDirection: "row",
296
+ alignItems: "center",
297
+ justifyContent: "space-between",
298
+ paddingVertical: 10,
299
+ paddingHorizontal: 12,
300
+ backgroundColor: night.color.surfaceElevated,
301
+ borderRadius: 8,
302
+ borderWidth: 1,
303
+ borderColor: night.color.border,
304
+ gap: 8
305
+ },
306
+ patternText: {
307
+ flex: 1,
308
+ fontSize: 12,
309
+ fontFamily: "monospace",
310
+ color: night.color.text
311
+ },
312
+ emptyText: {
313
+ fontSize: 11,
314
+ color: night.color.textTertiary,
315
+ paddingHorizontal: 16,
316
+ paddingTop: 8,
317
+ paddingBottom: 16,
318
+ fontFamily: "monospace"
319
+ },
320
+ howItWorksText: {
321
+ fontSize: 11,
322
+ color: night.color.textSecondary,
323
+ lineHeight: 16,
324
+ marginTop: 8,
325
+ paddingHorizontal: 16,
326
+ fontFamily: "monospace"
327
+ },
328
+ examplesContainer: {
329
+ paddingTop: 8,
330
+ paddingHorizontal: 16,
331
+ paddingBottom: 16,
332
+ borderTopWidth: 1,
333
+ borderTopColor: night.color.border,
334
+ marginTop: 12
335
+ },
336
+ examplesTitle: {
337
+ fontSize: 10,
338
+ fontWeight: "600",
339
+ color: night.color.textTertiary,
340
+ fontFamily: "monospace",
341
+ letterSpacing: 0.5,
342
+ marginBottom: 6
343
+ },
344
+ exampleItem: {
345
+ fontSize: 10,
346
+ color: night.color.textTertiary,
347
+ fontFamily: "monospace",
348
+ lineHeight: 16
349
+ }
350
+ });
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * ExportPreview — the collapsible "what will be copied" panel at the bottom
5
+ * of a copy-settings screen.
6
+ *
7
+ * Collapsed, it is a card: an eye icon, "Show Preview", a one-line summary
8
+ * ("14 events · ~12.3 KB (mock data)"), a chevron — and, when the estimated
9
+ * payload is big, an amber or red size warning under it. Expanded, it is a
10
+ * "Hide Preview" bar over whatever the tool renders (a DataViewer for JSON,
11
+ * a mono text block otherwise).
12
+ *
13
+ * network, events and highlight-updates each drew this (~120 lines apiece).
14
+ * Tools keep their own summary string, warning copy and body; the chrome
15
+ * and the size-threshold ladder live here.
16
+ */
17
+
18
+ import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
19
+ import { AlertTriangle, ChevronDown, ChevronUp, Eye } from "../../icons/index.js";
20
+ import { night } from "../night/nightTheme.js";
21
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
22
+ /** The two-step ladder every copy view used (thresholds differ per tool). */
23
+ export function sizeWarningLevel(bytes, thresholds) {
24
+ if (bytes >= thresholds.danger) return "danger";
25
+ if (bytes >= thresholds.warning) return "warning";
26
+ return "none";
27
+ }
28
+ const DEFAULT_WARNING = {
29
+ warning: "Large payload — preview may be slow",
30
+ danger: "Very large payload — may cause performance issues"
31
+ };
32
+ export function ExportPreview({
33
+ expanded,
34
+ onExpandedChange,
35
+ summary,
36
+ warningLevel = "none",
37
+ warningText = DEFAULT_WARNING,
38
+ testIDs,
39
+ renderBody
40
+ }) {
41
+ if (!expanded) {
42
+ const warningColor = warningLevel === "danger" ? night.color.danger : warningLevel === "warning" ? night.color.warning : night.color.textSecondary;
43
+ return /*#__PURE__*/_jsxs(View, {
44
+ style: styles.collapsed,
45
+ children: [/*#__PURE__*/_jsx(TouchableOpacity, {
46
+ style: styles.expandButton,
47
+ onPress: () => onExpandedChange(true),
48
+ testID: testIDs?.expand,
49
+ accessibilityRole: "button",
50
+ accessibilityLabel: "Show export preview",
51
+ children: /*#__PURE__*/_jsxs(View, {
52
+ style: styles.expandButtonContent,
53
+ children: [/*#__PURE__*/_jsx(Eye, {
54
+ size: 16,
55
+ color: night.color.info
56
+ }), /*#__PURE__*/_jsxs(View, {
57
+ style: styles.expandButtonTextContainer,
58
+ children: [/*#__PURE__*/_jsx(Text, {
59
+ style: styles.expandButtonTitle,
60
+ children: "Show Preview"
61
+ }), /*#__PURE__*/_jsx(Text, {
62
+ style: styles.expandButtonSubtitle,
63
+ testID: testIDs?.summary,
64
+ children: summary
65
+ })]
66
+ }), /*#__PURE__*/_jsx(ChevronDown, {
67
+ size: 16,
68
+ color: night.color.textTertiary
69
+ })]
70
+ })
71
+ }), warningLevel !== "none" ? /*#__PURE__*/_jsxs(View, {
72
+ style: [styles.sizeWarning, warningLevel === "danger" && styles.sizeWarningDanger],
73
+ testID: testIDs?.warning,
74
+ children: [/*#__PURE__*/_jsx(AlertTriangle, {
75
+ size: 12,
76
+ color: warningColor
77
+ }), /*#__PURE__*/_jsx(Text, {
78
+ style: [styles.sizeWarningText, {
79
+ color: warningColor
80
+ }],
81
+ children: warningLevel === "danger" ? warningText.danger : warningText.warning
82
+ })]
83
+ }) : null]
84
+ });
85
+ }
86
+ return /*#__PURE__*/_jsxs(View, {
87
+ children: [/*#__PURE__*/_jsxs(TouchableOpacity, {
88
+ style: styles.collapseButton,
89
+ onPress: () => onExpandedChange(false),
90
+ testID: testIDs?.collapse,
91
+ accessibilityRole: "button",
92
+ accessibilityLabel: "Hide export preview",
93
+ children: [/*#__PURE__*/_jsx(Text, {
94
+ style: styles.collapseButtonText,
95
+ children: "Hide Preview"
96
+ }), /*#__PURE__*/_jsx(ChevronUp, {
97
+ size: 14,
98
+ color: night.color.textSecondary
99
+ })]
100
+ }), renderBody()]
101
+ });
102
+ }
103
+ const styles = StyleSheet.create({
104
+ collapsed: {
105
+ gap: 8
106
+ },
107
+ expandButton: {
108
+ backgroundColor: night.color.surfaceElevated,
109
+ borderRadius: 8,
110
+ borderWidth: 1,
111
+ borderColor: night.color.border,
112
+ padding: 12
113
+ },
114
+ expandButtonContent: {
115
+ flexDirection: "row",
116
+ alignItems: "center",
117
+ gap: 10
118
+ },
119
+ expandButtonTextContainer: {
120
+ flex: 1
121
+ },
122
+ expandButtonTitle: {
123
+ fontSize: 13,
124
+ fontWeight: "600",
125
+ color: night.color.text
126
+ },
127
+ expandButtonSubtitle: {
128
+ fontSize: 11,
129
+ color: night.color.textSecondary,
130
+ marginTop: 2
131
+ },
132
+ collapseButton: {
133
+ flexDirection: "row",
134
+ alignItems: "center",
135
+ justifyContent: "center",
136
+ gap: 6,
137
+ paddingVertical: 8,
138
+ marginBottom: 8,
139
+ backgroundColor: night.color.surfaceElevated,
140
+ borderRadius: 6,
141
+ borderWidth: 1,
142
+ borderColor: night.color.border
143
+ },
144
+ collapseButtonText: {
145
+ fontSize: 12,
146
+ fontWeight: "500",
147
+ color: night.color.textSecondary
148
+ },
149
+ sizeWarning: {
150
+ flexDirection: "row",
151
+ alignItems: "center",
152
+ gap: 6,
153
+ paddingHorizontal: 10,
154
+ paddingVertical: 6,
155
+ backgroundColor: night.color.warningSoft,
156
+ borderRadius: 6,
157
+ borderWidth: 1,
158
+ borderColor: night.color.warning + "30"
159
+ },
160
+ sizeWarningDanger: {
161
+ backgroundColor: night.color.dangerSoft,
162
+ borderColor: night.color.danger + "30"
163
+ },
164
+ sizeWarningText: {
165
+ fontSize: 11,
166
+ fontWeight: "500",
167
+ flex: 1
168
+ }
169
+ });
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * InfoRow — the label / value line of every detail screen.
5
+ *
6
+ * Thirteen tools hand-rolled this (redux and zustand byte-for-byte). The
7
+ * night-theme recipe below is theirs: 11 px, tertiary label on the left,
8
+ * right-aligned value that truncates in the MIDDLE so both ends of an id or
9
+ * a path stay readable, optional monospace, optional color.
10
+ *
11
+ * `ellipsizeMode="middle"` truncates the RENDERED text and iOS reports the
12
+ * truncated string back, so anything a test reads off one of these rows has
13
+ * to be short enough to fit on the line.
14
+ */
15
+
16
+ import { StyleSheet, Text, View } from "react-native";
17
+ import { night } from "../night/nightTheme.js";
18
+ import { CopyButton } from "./CopyButton.js";
19
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
20
+ export function InfoRow({
21
+ label,
22
+ value,
23
+ valueColor,
24
+ mono = false,
25
+ copyable = false,
26
+ numberOfLines = 1,
27
+ testID,
28
+ style,
29
+ labelStyle,
30
+ valueStyle
31
+ }) {
32
+ const isText = typeof value === "string" || typeof value === "number";
33
+ return /*#__PURE__*/_jsxs(View, {
34
+ style: [styles.row, style],
35
+ children: [/*#__PURE__*/_jsx(Text, {
36
+ style: [styles.label, labelStyle],
37
+ numberOfLines: 1,
38
+ children: label
39
+ }), isText ? /*#__PURE__*/_jsx(Text, {
40
+ testID: testID,
41
+ style: [styles.value, mono && styles.valueMono, valueColor ? {
42
+ color: valueColor
43
+ } : undefined, valueStyle],
44
+ numberOfLines: numberOfLines,
45
+ ellipsizeMode: "middle",
46
+ children: String(value)
47
+ }) : /*#__PURE__*/_jsx(View, {
48
+ style: styles.valueNode,
49
+ testID: testID,
50
+ children: value
51
+ }), copyable && isText ? /*#__PURE__*/_jsx(CopyButton, {
52
+ value: String(value),
53
+ size: 12
54
+ }) : null]
55
+ });
56
+ }
57
+ const styles = StyleSheet.create({
58
+ row: {
59
+ flexDirection: "row",
60
+ alignItems: "center",
61
+ justifyContent: "space-between"
62
+ },
63
+ label: {
64
+ fontSize: 11,
65
+ color: night.color.textTertiary,
66
+ fontWeight: "500"
67
+ },
68
+ value: {
69
+ fontSize: 11,
70
+ color: night.color.text,
71
+ fontWeight: "500",
72
+ flex: 1,
73
+ textAlign: "right",
74
+ marginLeft: 12
75
+ },
76
+ valueMono: {
77
+ fontFamily: "monospace"
78
+ },
79
+ valueNode: {
80
+ flex: 1,
81
+ flexDirection: "row",
82
+ justifyContent: "flex-end",
83
+ alignItems: "center",
84
+ marginLeft: 12
85
+ }
86
+ });
@@ -139,16 +139,32 @@ export function HeaderSearch({
139
139
  onCancel,
140
140
  placeholder = "Search...",
141
141
  autoFocus = true,
142
- testID
142
+ testID,
143
+ containerTestID,
144
+ clearTestID,
145
+ accessibilityLabel,
146
+ onBlur,
147
+ iconSize = 12,
148
+ dismissOnBlur = false,
149
+ onDismiss,
150
+ clearOnlyWhenText = false,
151
+ inputProps,
152
+ containerNativeID
143
153
  }) {
144
154
  const inputRef = useRef(null);
155
+ // Set while the ✕ is pressed so the blur it causes doesn't dismiss first.
156
+ const clearPressRef = useRef(false);
145
157
  useEffect(() => {
146
158
  if (autoFocus) inputRef.current?.focus();
147
159
  }, [autoFocus]);
160
+ const dismiss = onDismiss ?? onCancel;
161
+ const showClear = !clearOnlyWhenText || value.length > 0;
148
162
  return /*#__PURE__*/_jsxs(View, {
149
163
  style: styles.searchContainer,
164
+ testID: containerTestID,
165
+ nativeID: containerNativeID,
150
166
  children: [/*#__PURE__*/_jsx(SearchIcon, {
151
- size: 12,
167
+ size: iconSize,
152
168
  color: night.color.textSecondary
153
169
  }), /*#__PURE__*/_jsx(TextInput, {
154
170
  ref: inputRef,
@@ -157,21 +173,38 @@ export function HeaderSearch({
157
173
  placeholderTextColor: night.color.placeholder,
158
174
  value: value,
159
175
  onChangeText: onChangeText,
176
+ onSubmitEditing: () => dismissOnBlur ? dismiss() : inputRef.current?.blur(),
177
+ onBlur: () => {
178
+ if (dismissOnBlur && !clearPressRef.current) dismiss();
179
+ onBlur?.();
180
+ },
160
181
  autoCorrect: false,
161
182
  autoCapitalize: "none",
183
+ returnKeyType: "search",
162
184
  testID: testID,
163
- accessibilityLabel: placeholder
164
- }), /*#__PURE__*/_jsx(TouchableOpacity, {
165
- onPress: onCancel,
185
+ accessibilityLabel: accessibilityLabel ?? placeholder,
186
+ ...inputProps
187
+ }), showClear ? /*#__PURE__*/_jsx(TouchableOpacity, {
188
+ onPress: onCancel
189
+ // react-native-web delays press-in ~50ms by default (native fires it
190
+ // immediately), which would put it AFTER the blur.
191
+ ,
192
+ delayPressIn: 0,
193
+ onPressIn: () => {
194
+ clearPressRef.current = true;
195
+ },
196
+ onPressOut: () => {
197
+ clearPressRef.current = false;
198
+ },
166
199
  style: styles.searchCancelButton,
167
200
  accessibilityRole: "button",
168
201
  accessibilityLabel: "Clear search",
169
- testID: testID ? `${testID}-clear` : undefined,
202
+ testID: clearTestID ?? (testID ? `${testID}-clear` : undefined),
170
203
  children: /*#__PURE__*/_jsx(X, {
171
204
  size: 12,
172
205
  color: night.color.textSecondary
173
206
  })
174
- })]
207
+ }) : null]
175
208
  });
176
209
  }
177
210