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