@buoy-gg/shared-ui 7.0.34 → 7.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/dataViewer/CyberpunkInput.js +3 -2
- package/lib/commonjs/dataViewer/DataTreeActionBar.js +3 -2
- package/lib/commonjs/dataViewer/DataTreeActionDock.js +2 -1
- package/lib/commonjs/dataViewer/DiffSummary.js +4 -3
- package/lib/commonjs/dataViewer/LiveExplorer.js +11 -10
- package/lib/commonjs/dataViewer/SplitDiffViewer.js +10 -9
- package/lib/commonjs/dataViewer/ThemedSplitView.js +12 -11
- package/lib/commonjs/dataViewer/ValueEditModal.js +6 -5
- package/lib/commonjs/dataViewer/VirtualizedDataExplorer.js +4 -3
- package/lib/commonjs/dataViewer/tree/TreeDiffViewer.js +15 -14
- package/lib/commonjs/hooks/safe-area-impl.js +1 -1
- package/lib/commonjs/icons/index.js +540 -1
- package/lib/commonjs/index.js +48 -0
- package/lib/commonjs/license/FreeAccountPrompt.js +2 -1
- package/lib/commonjs/license/LicenseEntryModal.js +2 -1
- package/lib/commonjs/sync/keyedArrays.js +209 -0
- package/lib/commonjs/sync/toolAttention.test.js +51 -0
- package/lib/commonjs/sync/toolUiBridge.js +58 -0
- package/lib/commonjs/sync/typedEdit.js +228 -0
- package/lib/commonjs/sync/valuePath.js +337 -0
- package/lib/commonjs/sync/valueShape.js +161 -0
- package/lib/commonjs/ui/components/ChangeRow.js +2 -1
- package/lib/commonjs/ui/components/ClipboardHintBanner.js +2 -1
- package/lib/commonjs/ui/components/CompactRow.js +3 -2
- package/lib/commonjs/ui/components/DataInspector.js +3 -2
- package/lib/commonjs/ui/components/DetailView.js +2 -1
- package/lib/commonjs/ui/components/DynamicFilterView.js +8 -7
- package/lib/commonjs/ui/components/EntityFilterView.js +9 -8
- package/lib/commonjs/ui/components/EventHistoryViewer/CompareBar.js +5 -4
- package/lib/commonjs/ui/components/EventHistoryViewer/DiffModeTabs.js +2 -1
- package/lib/commonjs/ui/components/EventHistoryViewer/EventPickerModal.js +5 -4
- package/lib/commonjs/ui/components/EventStepperFooter.js +4 -3
- package/lib/commonjs/ui/components/ExpandablePopover.js +48 -8
- package/lib/commonjs/ui/components/ExpandedInfoRow.js +3 -2
- package/lib/commonjs/ui/components/FilterComponents.js +2 -1
- package/lib/commonjs/ui/components/InfoRow.js +2 -1
- package/lib/commonjs/ui/components/Pill.js +2 -1
- package/lib/commonjs/ui/components/ToolFooter.js +3 -2
- package/lib/commonjs/ui/console/CyberpunkSectionButton.js +3 -2
- package/lib/commonjs/ui/fonts.js +12 -0
- package/lib/commonjs/ui/gameUI/components/GameUICollapsibleSection.js +4 -3
- package/lib/commonjs/ui/gameUI/components/GameUICompactStats.js +12 -11
- package/lib/commonjs/ui/gameUI/components/GameUIIssuesList.js +9 -8
- package/lib/commonjs/ui/gameUI/components/GameUIStatusHeader.js +4 -3
- package/lib/commonjs/ui/index.js +8 -0
- package/lib/commonjs/ui/toolTheme.js +4 -3
- package/lib/module/dataViewer/CyberpunkInput.js +3 -2
- package/lib/module/dataViewer/DataTreeActionBar.js +3 -2
- package/lib/module/dataViewer/DataTreeActionDock.js +2 -1
- package/lib/module/dataViewer/DiffSummary.js +4 -3
- package/lib/module/dataViewer/LiveExplorer.js +11 -11
- package/lib/module/dataViewer/SplitDiffViewer.js +10 -9
- package/lib/module/dataViewer/ThemedSplitView.js +12 -11
- package/lib/module/dataViewer/ValueEditModal.js +6 -5
- package/lib/module/dataViewer/VirtualizedDataExplorer.js +5 -4
- package/lib/module/dataViewer/tree/TreeDiffViewer.js +15 -15
- package/lib/module/hooks/safe-area-impl.js +1 -1
- package/lib/module/icons/index.js +29 -2
- package/lib/module/index.js +4 -0
- package/lib/module/license/FreeAccountPrompt.js +2 -2
- package/lib/module/license/LicenseEntryModal.js +3 -3
- package/lib/module/sync/keyedArrays.js +204 -0
- package/lib/module/sync/toolAttention.test.js +50 -0
- package/lib/module/sync/toolUiBridge.js +55 -0
- package/lib/module/sync/typedEdit.js +220 -0
- package/lib/module/sync/valuePath.js +330 -0
- package/lib/module/sync/valueShape.js +153 -0
- package/lib/module/ui/components/ChangeRow.js +2 -1
- package/lib/module/ui/components/ClipboardHintBanner.js +2 -1
- package/lib/module/ui/components/CompactRow.js +3 -2
- package/lib/module/ui/components/DataInspector.js +3 -2
- package/lib/module/ui/components/DetailView.js +2 -1
- package/lib/module/ui/components/DynamicFilterView.js +8 -7
- package/lib/module/ui/components/EntityFilterView.js +9 -8
- package/lib/module/ui/components/EventHistoryViewer/CompareBar.js +6 -5
- package/lib/module/ui/components/EventHistoryViewer/DiffModeTabs.js +3 -2
- package/lib/module/ui/components/EventHistoryViewer/EventPickerModal.js +6 -5
- package/lib/module/ui/components/EventStepperFooter.js +4 -3
- package/lib/module/ui/components/ExpandablePopover.js +48 -8
- package/lib/module/ui/components/ExpandedInfoRow.js +3 -2
- package/lib/module/ui/components/FilterComponents.js +2 -2
- package/lib/module/ui/components/InfoRow.js +2 -1
- package/lib/module/ui/components/Pill.js +2 -1
- package/lib/module/ui/components/ToolFooter.js +3 -2
- package/lib/module/ui/console/CyberpunkSectionButton.js +3 -2
- package/lib/module/ui/fonts.js +8 -0
- package/lib/module/ui/gameUI/components/GameUICollapsibleSection.js +4 -3
- package/lib/module/ui/gameUI/components/GameUICompactStats.js +12 -11
- package/lib/module/ui/gameUI/components/GameUIIssuesList.js +9 -8
- package/lib/module/ui/gameUI/components/GameUIStatusHeader.js +4 -3
- package/lib/module/ui/index.js +3 -0
- package/lib/module/ui/toolTheme.js +4 -4
- package/lib/typescript/commonjs/dataViewer/CyberpunkInput.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/DataTreeActionBar.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/DataTreeActionDock.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/DiffSummary.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/LiveExplorer.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/SplitDiffViewer.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/ThemedSplitView.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/ValueEditModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/VirtualizedDataExplorer.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/tree/TreeDiffViewer.d.ts.map +1 -1
- package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/commonjs/icons/index.d.ts +4 -1
- package/lib/typescript/commonjs/icons/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +4 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/license/FreeAccountPrompt.d.ts.map +1 -1
- package/lib/typescript/commonjs/license/LicenseEntryModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/sync/keyedArrays.d.ts +35 -0
- package/lib/typescript/commonjs/sync/keyedArrays.d.ts.map +1 -0
- package/lib/typescript/commonjs/sync/toolAttention.test.d.ts +2 -0
- package/lib/typescript/commonjs/sync/toolAttention.test.d.ts.map +1 -0
- package/lib/typescript/commonjs/sync/toolUiBridge.d.ts +25 -0
- package/lib/typescript/commonjs/sync/toolUiBridge.d.ts.map +1 -1
- package/lib/typescript/commonjs/sync/typedEdit.d.ts +70 -0
- package/lib/typescript/commonjs/sync/typedEdit.d.ts.map +1 -0
- package/lib/typescript/commonjs/sync/valuePath.d.ts +52 -0
- package/lib/typescript/commonjs/sync/valuePath.d.ts.map +1 -0
- package/lib/typescript/commonjs/sync/valueShape.d.ts +77 -0
- package/lib/typescript/commonjs/sync/valueShape.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ChangeRow.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ClipboardHintBanner.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/CompactRow.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/DataInspector.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/DetailView.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/DynamicFilterView.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/EntityFilterView.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/EventHistoryViewer/CompareBar.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/EventHistoryViewer/DiffModeTabs.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/EventHistoryViewer/EventPickerModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/EventStepperFooter.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ExpandablePopover.d.ts +18 -1
- package/lib/typescript/commonjs/ui/components/ExpandablePopover.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ExpandedInfoRow.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/FilterComponents.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/InfoRow.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/Pill.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ToolFooter.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/console/CyberpunkSectionButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/fonts.d.ts +7 -0
- package/lib/typescript/commonjs/ui/fonts.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/gameUI/components/GameUICollapsibleSection.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/gameUI/components/GameUICompactStats.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/gameUI/components/GameUIIssuesList.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/gameUI/components/GameUIStatusHeader.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/index.d.ts +1 -0
- package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/toolTheme.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/CyberpunkInput.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/DataTreeActionBar.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/DataTreeActionDock.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/DiffSummary.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/LiveExplorer.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/SplitDiffViewer.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/ThemedSplitView.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/ValueEditModal.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/VirtualizedDataExplorer.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/tree/TreeDiffViewer.d.ts.map +1 -1
- package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/module/icons/index.d.ts +4 -1
- package/lib/typescript/module/icons/index.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +4 -0
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/license/FreeAccountPrompt.d.ts.map +1 -1
- package/lib/typescript/module/license/LicenseEntryModal.d.ts.map +1 -1
- package/lib/typescript/module/sync/keyedArrays.d.ts +35 -0
- package/lib/typescript/module/sync/keyedArrays.d.ts.map +1 -0
- package/lib/typescript/module/sync/toolAttention.test.d.ts +2 -0
- package/lib/typescript/module/sync/toolAttention.test.d.ts.map +1 -0
- package/lib/typescript/module/sync/toolUiBridge.d.ts +25 -0
- package/lib/typescript/module/sync/toolUiBridge.d.ts.map +1 -1
- package/lib/typescript/module/sync/typedEdit.d.ts +70 -0
- package/lib/typescript/module/sync/typedEdit.d.ts.map +1 -0
- package/lib/typescript/module/sync/valuePath.d.ts +52 -0
- package/lib/typescript/module/sync/valuePath.d.ts.map +1 -0
- package/lib/typescript/module/sync/valueShape.d.ts +77 -0
- package/lib/typescript/module/sync/valueShape.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ChangeRow.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ClipboardHintBanner.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/CompactRow.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/DataInspector.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/DetailView.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/DynamicFilterView.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/EntityFilterView.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/EventHistoryViewer/CompareBar.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/EventHistoryViewer/DiffModeTabs.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/EventHistoryViewer/EventPickerModal.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/EventStepperFooter.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ExpandablePopover.d.ts +18 -1
- package/lib/typescript/module/ui/components/ExpandablePopover.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ExpandedInfoRow.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/FilterComponents.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/InfoRow.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/Pill.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ToolFooter.d.ts.map +1 -1
- package/lib/typescript/module/ui/console/CyberpunkSectionButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/fonts.d.ts +7 -0
- package/lib/typescript/module/ui/fonts.d.ts.map +1 -0
- package/lib/typescript/module/ui/gameUI/components/GameUICollapsibleSection.d.ts.map +1 -1
- package/lib/typescript/module/ui/gameUI/components/GameUICompactStats.d.ts.map +1 -1
- package/lib/typescript/module/ui/gameUI/components/GameUIIssuesList.d.ts.map +1 -1
- package/lib/typescript/module/ui/gameUI/components/GameUIStatusHeader.d.ts.map +1 -1
- package/lib/typescript/module/ui/index.d.ts +1 -0
- package/lib/typescript/module/ui/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/toolTheme.d.ts.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A compact type sketch of a runtime value — one implementation, shared by every
|
|
5
|
+
* adapter that hands data to a model.
|
|
6
|
+
*
|
|
7
|
+
* WHY. A model cannot write a well-formed item into a list it has never seen the
|
|
8
|
+
* shape of, and we were not showing it. Measured on `cart/bag-still-zustand`: the
|
|
9
|
+
* rendered prompt is 83,000 characters and the words `lineId`, `itemId`,
|
|
10
|
+
* `sizeId`, `addonIds` and `unitPrice` appear in it ZERO times. Every model
|
|
11
|
+
* "failing" that case invented a line shape because inventing was the only move
|
|
12
|
+
* available. The zustand typed-edit guard would have caught the invention — but
|
|
13
|
+
* only on a list that already holds an item, since it builds its template from
|
|
14
|
+
* `list[0]`. On an EMPTY list there is no template, the guard has nothing to
|
|
15
|
+
* compare against, and the invented shape is written silently.
|
|
16
|
+
*
|
|
17
|
+
* So the sketch has two jobs, and the second is the one that pays:
|
|
18
|
+
*
|
|
19
|
+
* 1. Say what the items in a list look like, so an addition can match.
|
|
20
|
+
* 2. Say when NOTHING knows — an empty list's item shape is not merely
|
|
21
|
+
* unread, it is unknowable from runtime state, and the honest answer is to
|
|
22
|
+
* admit that rather than let a guess through unremarked.
|
|
23
|
+
*
|
|
24
|
+
* It is deliberately tiny. A sketch of a 120-line bag is the same size as a
|
|
25
|
+
* sketch of a 2-line one, so unlike the data it survives the engine's 24,000-
|
|
26
|
+
* character result cap — which is the whole point, because the cases where the
|
|
27
|
+
* model most needs the shape are exactly the ones where the data got cut off.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
const isPlainObject = v => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
31
|
+
|
|
32
|
+
/** Beyond this the sketch stops being cheaper to read than the data. */
|
|
33
|
+
const MAX_DEPTH = 3;
|
|
34
|
+
const MAX_KEYS = 24;
|
|
35
|
+
/**
|
|
36
|
+
* Hard caps on `listShapes`. MAX_DEPTH bounds how DEEP it goes; nothing bounded
|
|
37
|
+
* how WIDE it went, and it walks every entry of every object at each permitted
|
|
38
|
+
* level. A store holding a few hundred keyed records therefore produced a
|
|
39
|
+
* "compact" sketch larger than the data it was standing in for — in a value
|
|
40
|
+
* that rides in every prompt. Depth is not a size budget.
|
|
41
|
+
*/
|
|
42
|
+
const MAX_LIST_PATHS = 40;
|
|
43
|
+
const MAX_ENTRIES_VISITED = 600;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* `{lineId: string, qty: number, addonIds: string[]}` — a one-line type for a
|
|
47
|
+
* value, built from the value itself.
|
|
48
|
+
*
|
|
49
|
+
* An array is described by its FIRST item, because a list whose items disagree
|
|
50
|
+
* is a list nothing can safely add to and the guard will say so anyway. An empty
|
|
51
|
+
* array is `unknown[]`, which is the true answer and the one that matters: it
|
|
52
|
+
* tells a reader that adding to this list is unchecked.
|
|
53
|
+
*/
|
|
54
|
+
export function shapeOf(value, depth = 0) {
|
|
55
|
+
if (value === null) return "null";
|
|
56
|
+
if (Array.isArray(value)) {
|
|
57
|
+
if (!value.length) return "unknown[]";
|
|
58
|
+
if (depth >= MAX_DEPTH) return "…[]";
|
|
59
|
+
const inner = shapeOf(value[0], depth + 1);
|
|
60
|
+
return inner.includes(" ") || inner.endsWith("]") ? `(${inner})[]` : `${inner}[]`;
|
|
61
|
+
}
|
|
62
|
+
if (isPlainObject(value)) {
|
|
63
|
+
if (depth >= MAX_DEPTH) return "{…}";
|
|
64
|
+
const keys = Object.keys(value);
|
|
65
|
+
const shown = keys.slice(0, MAX_KEYS);
|
|
66
|
+
const body = shown.map(k => `${k}: ${shapeOf(value[k], depth + 1)}`).join(", ");
|
|
67
|
+
const more = keys.length > shown.length ? `, +${keys.length - shown.length} more` : "";
|
|
68
|
+
return `{${body}${more}}`;
|
|
69
|
+
}
|
|
70
|
+
const t = typeof value;
|
|
71
|
+
return t === "undefined" ? "undefined" : t === "function" ? "function" : t;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Every list inside a value, with the shape of what goes in it.
|
|
75
|
+
*
|
|
76
|
+
* This is what a caller needs before adding to a list, and it is the part that
|
|
77
|
+
* cannot be recovered from a truncated read of the data itself.
|
|
78
|
+
*
|
|
79
|
+
* A list with `item: undefined` is the warning case: it is empty, so its item
|
|
80
|
+
* shape exists nowhere in the running app — not in the store, not in the
|
|
81
|
+
* persisted copy, not in this sketch. Anything added to it goes in unchecked.
|
|
82
|
+
*/
|
|
83
|
+
export function listShapes(value, path = "", out = [], depth = 0, budget = {
|
|
84
|
+
visited: 0
|
|
85
|
+
}) {
|
|
86
|
+
if (depth > MAX_DEPTH) return out;
|
|
87
|
+
// Two independent stops: enough lists described, or enough of the value
|
|
88
|
+
// walked. The second is what a wide-but-shallow store hits.
|
|
89
|
+
if (out.length >= MAX_LIST_PATHS || budget.visited >= MAX_ENTRIES_VISITED) return out;
|
|
90
|
+
if (Array.isArray(value)) {
|
|
91
|
+
const first = value[0];
|
|
92
|
+
out.push({
|
|
93
|
+
path: path || "(root)",
|
|
94
|
+
length: value.length,
|
|
95
|
+
...(value.length ? {
|
|
96
|
+
item: shapeOf(first)
|
|
97
|
+
} : {})
|
|
98
|
+
});
|
|
99
|
+
// One level into the items, so `lines[].addonIds` is reachable too.
|
|
100
|
+
if (value.length && isPlainObject(first)) {
|
|
101
|
+
for (const [k, v] of Object.entries(first)) {
|
|
102
|
+
if (++budget.visited >= MAX_ENTRIES_VISITED) break;
|
|
103
|
+
listShapes(v, path ? `${path}[].${k}` : `[].${k}`, out, depth + 1, budget);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
if (isPlainObject(value)) {
|
|
109
|
+
for (const [k, v] of Object.entries(value)) {
|
|
110
|
+
if (++budget.visited >= MAX_ENTRIES_VISITED) break;
|
|
111
|
+
listShapes(v, path ? `${path}.${k}` : k, out, depth + 1, budget);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** True when a sketch stopped early, so a caller can say so rather than imply completeness. */
|
|
118
|
+
export function shapesWereTruncated(value) {
|
|
119
|
+
const budget = {
|
|
120
|
+
visited: 0
|
|
121
|
+
};
|
|
122
|
+
const out = listShapes(value, "", [], 0, budget);
|
|
123
|
+
return out.length >= MAX_LIST_PATHS || budget.visited >= MAX_ENTRIES_VISITED;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* The lists in a value that a caller could add to WITHOUT any way to know the
|
|
128
|
+
* item shape. Empty by definition on a healthy value; non-empty means a write
|
|
129
|
+
* into one of these paths cannot be checked by anything.
|
|
130
|
+
*/
|
|
131
|
+
export function unshapedLists(value) {
|
|
132
|
+
return listShapes(value).filter(l => l.item === undefined).map(l => l.path);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* The sketch an adapter attaches to a read: the value's own type, plus the item
|
|
137
|
+
* type of every list in it.
|
|
138
|
+
*
|
|
139
|
+
* Returns undefined when there is nothing worth saying (a scalar, or an object
|
|
140
|
+
* holding no lists) so adapters can spread it and add no noise.
|
|
141
|
+
*/
|
|
142
|
+
export function shapeSummary(value) {
|
|
143
|
+
if (value === undefined) return undefined;
|
|
144
|
+
const lists = listShapes(value);
|
|
145
|
+
const shape = shapeOf(value);
|
|
146
|
+
if (!lists.length && !isPlainObject(value) && !Array.isArray(value)) return undefined;
|
|
147
|
+
return lists.length ? {
|
|
148
|
+
shape,
|
|
149
|
+
lists
|
|
150
|
+
} : {
|
|
151
|
+
shape
|
|
152
|
+
};
|
|
153
|
+
}
|
|
@@ -23,6 +23,7 @@ import { buoyColors } from "../gameUI/constants/gameUIColors.js";
|
|
|
23
23
|
import { CompactRow } from "./CompactRow.js";
|
|
24
24
|
import { Clock, Zap } from "../../icons/index.js";
|
|
25
25
|
import { RelativeTime } from "../../utils/time/RelativeTime.js";
|
|
26
|
+
import { monoFont } from "../fonts.js";
|
|
26
27
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
27
28
|
export function ChangeRow({
|
|
28
29
|
statusColor,
|
|
@@ -97,7 +98,7 @@ const styles = StyleSheet.create({
|
|
|
97
98
|
badgeText: {
|
|
98
99
|
fontSize: 11,
|
|
99
100
|
fontWeight: "600",
|
|
100
|
-
fontFamily:
|
|
101
|
+
fontFamily: monoFont
|
|
101
102
|
},
|
|
102
103
|
iconBadge: {
|
|
103
104
|
paddingHorizontal: 4
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { memo, useCallback } from "react";
|
|
12
12
|
import { View, Text, TouchableOpacity, StyleSheet, Modal, Pressable } from "react-native";
|
|
13
13
|
import { gameUIColors } from "../gameUI/index.js";
|
|
14
|
+
import { monoFont } from "../fonts.js";
|
|
14
15
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
15
16
|
/**
|
|
16
17
|
* A modal hint that teaches users about iOS Simulator clipboard sync
|
|
@@ -125,7 +126,7 @@ const styles = StyleSheet.create({
|
|
|
125
126
|
textAlign: "center"
|
|
126
127
|
},
|
|
127
128
|
menuPath: {
|
|
128
|
-
fontFamily:
|
|
129
|
+
fontFamily: monoFont,
|
|
129
130
|
fontSize: 12,
|
|
130
131
|
color: gameUIColors.primary,
|
|
131
132
|
fontWeight: "600"
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
|
|
4
4
|
import { ChevronDown, ChevronRight } from "../../icons/index.js";
|
|
5
5
|
import { night } from "../night/nightTheme.js";
|
|
6
|
+
import { monoFont } from "../fonts.js";
|
|
6
7
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
8
|
export function CompactRow({
|
|
8
9
|
statusDotColor,
|
|
@@ -221,7 +222,7 @@ const styles = StyleSheet.create({
|
|
|
221
222
|
paddingHorizontal: 12
|
|
222
223
|
},
|
|
223
224
|
queryHash: {
|
|
224
|
-
fontFamily:
|
|
225
|
+
fontFamily: monoFont,
|
|
225
226
|
fontSize: 12,
|
|
226
227
|
color: night.color.text,
|
|
227
228
|
lineHeight: 16
|
|
@@ -265,6 +266,6 @@ const styles = StyleSheet.create({
|
|
|
265
266
|
bottomRightText: {
|
|
266
267
|
fontSize: 9,
|
|
267
268
|
color: night.color.textTertiary,
|
|
268
|
-
fontFamily:
|
|
269
|
+
fontFamily: monoFont
|
|
269
270
|
}
|
|
270
271
|
});
|
|
@@ -5,6 +5,7 @@ import { View, Text, StyleSheet, ScrollView, TouchableOpacity, TextInput } from
|
|
|
5
5
|
import { Search, Edit3, Check, X } from "../../icons/index.js";
|
|
6
6
|
import { gameUIColors } from "../gameUI/index.js";
|
|
7
7
|
import { CopyButton } from "./CopyButton.js";
|
|
8
|
+
import { monoFont } from "../fonts.js";
|
|
8
9
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
10
|
export function DataInspector({
|
|
10
11
|
data,
|
|
@@ -264,14 +265,14 @@ const styles = StyleSheet.create({
|
|
|
264
265
|
maxHeight: 300
|
|
265
266
|
},
|
|
266
267
|
codeText: {
|
|
267
|
-
fontFamily:
|
|
268
|
+
fontFamily: monoFont,
|
|
268
269
|
fontSize: 11,
|
|
269
270
|
color: gameUIColors.text,
|
|
270
271
|
padding: 12,
|
|
271
272
|
lineHeight: 16
|
|
272
273
|
},
|
|
273
274
|
editor: {
|
|
274
|
-
fontFamily:
|
|
275
|
+
fontFamily: monoFont,
|
|
275
276
|
fontSize: 11,
|
|
276
277
|
color: gameUIColors.text,
|
|
277
278
|
padding: 12,
|
|
@@ -5,6 +5,7 @@ import { View, Text, StyleSheet, ScrollView, TouchableOpacity } from "react-nati
|
|
|
5
5
|
import { gameUIColors } from "../gameUI/index.js";
|
|
6
6
|
import { ModalHeader } from "./ModalHeader.js";
|
|
7
7
|
import { CopyButton } from "./CopyButton.js";
|
|
8
|
+
import { monoFont } from "../fonts.js";
|
|
8
9
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
10
|
export function DetailView({
|
|
10
11
|
children,
|
|
@@ -293,7 +294,7 @@ const styles = StyleSheet.create({
|
|
|
293
294
|
},
|
|
294
295
|
dataText: {
|
|
295
296
|
fontSize: 12,
|
|
296
|
-
fontFamily:
|
|
297
|
+
fontFamily: monoFont,
|
|
297
298
|
color: gameUIColors.text
|
|
298
299
|
},
|
|
299
300
|
statusBar: {
|
|
@@ -8,6 +8,7 @@ import { FilterList, AddFilterInput, AddFilterButton } from "./FilterComponents.
|
|
|
8
8
|
import { useFilterManager } from "../../hooks/useFilterManager.js";
|
|
9
9
|
import { buoyColors } from "../gameUI/constants/gameUIColors.js";
|
|
10
10
|
import { night } from "../night/nightTheme.js";
|
|
11
|
+
import { monoFont } from "../fonts.js";
|
|
11
12
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
12
13
|
export function DynamicFilterView({
|
|
13
14
|
sections = [],
|
|
@@ -489,7 +490,7 @@ const styles = StyleSheet.create({
|
|
|
489
490
|
fontSize: 14,
|
|
490
491
|
fontWeight: "700",
|
|
491
492
|
color: night.color.text,
|
|
492
|
-
fontFamily:
|
|
493
|
+
fontFamily: monoFont,
|
|
493
494
|
marginTop: 3,
|
|
494
495
|
marginBottom: 1,
|
|
495
496
|
textShadowColor: "rgba(0, 0, 0, 0.2)",
|
|
@@ -503,7 +504,7 @@ const styles = StyleSheet.create({
|
|
|
503
504
|
fontSize: 11,
|
|
504
505
|
fontWeight: "500",
|
|
505
506
|
color: night.color.textTertiary,
|
|
506
|
-
fontFamily:
|
|
507
|
+
fontFamily: monoFont,
|
|
507
508
|
marginTop: 3,
|
|
508
509
|
marginBottom: 1
|
|
509
510
|
},
|
|
@@ -547,7 +548,7 @@ const styles = StyleSheet.create({
|
|
|
547
548
|
fontSize: 13,
|
|
548
549
|
fontWeight: "700",
|
|
549
550
|
letterSpacing: 0.3,
|
|
550
|
-
fontFamily:
|
|
551
|
+
fontFamily: monoFont
|
|
551
552
|
},
|
|
552
553
|
activeFiltersSection: {
|
|
553
554
|
backgroundColor: night.color.surface,
|
|
@@ -686,7 +687,7 @@ const styles = StyleSheet.create({
|
|
|
686
687
|
flex: 1,
|
|
687
688
|
fontSize: 11,
|
|
688
689
|
color: night.color.text,
|
|
689
|
-
fontFamily:
|
|
690
|
+
fontFamily: monoFont,
|
|
690
691
|
marginRight: 8
|
|
691
692
|
},
|
|
692
693
|
howItWorksSection: {
|
|
@@ -705,7 +706,7 @@ const styles = StyleSheet.create({
|
|
|
705
706
|
marginBottom: 12,
|
|
706
707
|
marginTop: 8,
|
|
707
708
|
paddingHorizontal: 16,
|
|
708
|
-
fontFamily:
|
|
709
|
+
fontFamily: monoFont
|
|
709
710
|
},
|
|
710
711
|
examplesContainer: {
|
|
711
712
|
paddingTop: 8,
|
|
@@ -718,14 +719,14 @@ const styles = StyleSheet.create({
|
|
|
718
719
|
fontSize: 10,
|
|
719
720
|
fontWeight: "600",
|
|
720
721
|
color: night.color.textTertiary,
|
|
721
|
-
fontFamily:
|
|
722
|
+
fontFamily: monoFont,
|
|
722
723
|
letterSpacing: 0.5,
|
|
723
724
|
marginBottom: 6
|
|
724
725
|
},
|
|
725
726
|
exampleItem: {
|
|
726
727
|
fontSize: 10,
|
|
727
728
|
color: night.color.textTertiary,
|
|
728
|
-
fontFamily:
|
|
729
|
+
fontFamily: monoFont,
|
|
729
730
|
lineHeight: 16
|
|
730
731
|
},
|
|
731
732
|
previewSection: {
|
|
@@ -23,6 +23,7 @@ import { Filter, X } from "../../icons/index.js";
|
|
|
23
23
|
import { night } from "../night/nightTheme.js";
|
|
24
24
|
import { SectionHeader } from "./SectionHeader.js";
|
|
25
25
|
import { AddFilterButton, AddFilterInput } from "./FilterComponents.js";
|
|
26
|
+
import { monoFont } from "../fonts.js";
|
|
26
27
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
27
28
|
/** True if any active pattern hides this entity. */
|
|
28
29
|
function isHidden(entity, ignoredPatterns) {
|
|
@@ -264,7 +265,7 @@ const styles = StyleSheet.create({
|
|
|
264
265
|
flex: 1,
|
|
265
266
|
fontSize: 12,
|
|
266
267
|
fontWeight: "600",
|
|
267
|
-
fontFamily:
|
|
268
|
+
fontFamily: monoFont
|
|
268
269
|
},
|
|
269
270
|
entityTextHidden: {
|
|
270
271
|
color: night.color.textTertiary,
|
|
@@ -274,12 +275,12 @@ const styles = StyleSheet.create({
|
|
|
274
275
|
fontSize: 10,
|
|
275
276
|
fontWeight: "500",
|
|
276
277
|
color: night.color.textTertiary,
|
|
277
|
-
fontFamily:
|
|
278
|
+
fontFamily: monoFont
|
|
278
279
|
},
|
|
279
280
|
addLabel: {
|
|
280
281
|
fontSize: 10,
|
|
281
282
|
fontWeight: "600",
|
|
282
|
-
fontFamily:
|
|
283
|
+
fontFamily: monoFont
|
|
283
284
|
},
|
|
284
285
|
addInputWrapper: {
|
|
285
286
|
paddingHorizontal: 16,
|
|
@@ -306,7 +307,7 @@ const styles = StyleSheet.create({
|
|
|
306
307
|
patternText: {
|
|
307
308
|
flex: 1,
|
|
308
309
|
fontSize: 12,
|
|
309
|
-
fontFamily:
|
|
310
|
+
fontFamily: monoFont,
|
|
310
311
|
color: night.color.text
|
|
311
312
|
},
|
|
312
313
|
emptyText: {
|
|
@@ -315,7 +316,7 @@ const styles = StyleSheet.create({
|
|
|
315
316
|
paddingHorizontal: 16,
|
|
316
317
|
paddingTop: 8,
|
|
317
318
|
paddingBottom: 16,
|
|
318
|
-
fontFamily:
|
|
319
|
+
fontFamily: monoFont
|
|
319
320
|
},
|
|
320
321
|
howItWorksText: {
|
|
321
322
|
fontSize: 11,
|
|
@@ -323,7 +324,7 @@ const styles = StyleSheet.create({
|
|
|
323
324
|
lineHeight: 16,
|
|
324
325
|
marginTop: 8,
|
|
325
326
|
paddingHorizontal: 16,
|
|
326
|
-
fontFamily:
|
|
327
|
+
fontFamily: monoFont
|
|
327
328
|
},
|
|
328
329
|
examplesContainer: {
|
|
329
330
|
paddingTop: 8,
|
|
@@ -337,14 +338,14 @@ const styles = StyleSheet.create({
|
|
|
337
338
|
fontSize: 10,
|
|
338
339
|
fontWeight: "600",
|
|
339
340
|
color: night.color.textTertiary,
|
|
340
|
-
fontFamily:
|
|
341
|
+
fontFamily: monoFont,
|
|
341
342
|
letterSpacing: 0.5,
|
|
342
343
|
marginBottom: 6
|
|
343
344
|
},
|
|
344
345
|
exampleItem: {
|
|
345
346
|
fontSize: 10,
|
|
346
347
|
color: night.color.textTertiary,
|
|
347
|
-
fontFamily:
|
|
348
|
+
fontFamily: monoFont,
|
|
348
349
|
lineHeight: 16
|
|
349
350
|
}
|
|
350
351
|
});
|
|
@@ -12,11 +12,12 @@ import React, { memo } from "react";
|
|
|
12
12
|
import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
|
|
13
13
|
import { macOSColors } from "../../gameUI/constants/macOSDesignSystemColors.js";
|
|
14
14
|
import { ChevronLeft, ChevronRight } from "../../../icons/lucide-icons.js";
|
|
15
|
-
import {
|
|
15
|
+
import { monoFont } from "../../fonts.js";
|
|
16
16
|
/**
|
|
17
17
|
* CompareBar displays a side-by-side comparison of two events
|
|
18
18
|
* with optional navigation controls for any-to-any compare mode.
|
|
19
19
|
*/
|
|
20
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
20
21
|
export const CompareBar = /*#__PURE__*/memo(function CompareBar({
|
|
21
22
|
leftEvent,
|
|
22
23
|
rightEvent,
|
|
@@ -150,7 +151,7 @@ const styles = StyleSheet.create({
|
|
|
150
151
|
},
|
|
151
152
|
label: {
|
|
152
153
|
fontSize: 10,
|
|
153
|
-
fontFamily:
|
|
154
|
+
fontFamily: monoFont,
|
|
154
155
|
fontWeight: "700",
|
|
155
156
|
letterSpacing: 0.5,
|
|
156
157
|
textTransform: "uppercase"
|
|
@@ -185,17 +186,17 @@ const styles = StyleSheet.create({
|
|
|
185
186
|
index: {
|
|
186
187
|
fontSize: 10,
|
|
187
188
|
color: macOSColors.text.secondary,
|
|
188
|
-
fontFamily:
|
|
189
|
+
fontFamily: monoFont
|
|
189
190
|
},
|
|
190
191
|
time: {
|
|
191
192
|
fontSize: 11,
|
|
192
193
|
color: macOSColors.text.primary,
|
|
193
|
-
fontFamily:
|
|
194
|
+
fontFamily: monoFont
|
|
194
195
|
},
|
|
195
196
|
relative: {
|
|
196
197
|
fontSize: 10,
|
|
197
198
|
color: macOSColors.text.secondary,
|
|
198
|
-
fontFamily:
|
|
199
|
+
fontFamily: monoFont
|
|
199
200
|
},
|
|
200
201
|
divider: {
|
|
201
202
|
width: 1,
|
|
@@ -11,11 +11,12 @@
|
|
|
11
11
|
import React, { memo } from "react";
|
|
12
12
|
import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
|
|
13
13
|
import { macOSColors } from "../../gameUI/constants/macOSDesignSystemColors.js";
|
|
14
|
-
import {
|
|
14
|
+
import { monoFont } from "../../fonts.js";
|
|
15
15
|
/**
|
|
16
16
|
* DiffModeTabs displays a horizontal tab bar for switching
|
|
17
17
|
* between different diff visualization modes.
|
|
18
18
|
*/
|
|
19
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
19
20
|
export const DiffModeTabs = /*#__PURE__*/memo(function DiffModeTabs({
|
|
20
21
|
tabs,
|
|
21
22
|
activeTab,
|
|
@@ -79,7 +80,7 @@ const styles = StyleSheet.create({
|
|
|
79
80
|
},
|
|
80
81
|
tabText: {
|
|
81
82
|
fontSize: 11,
|
|
82
|
-
fontFamily:
|
|
83
|
+
fontFamily: monoFont,
|
|
83
84
|
fontWeight: "600",
|
|
84
85
|
color: macOSColors.text.secondary,
|
|
85
86
|
letterSpacing: 0.5
|
|
@@ -13,11 +13,12 @@ import { View, Text, TouchableOpacity, ScrollView, StyleSheet } from "react-nati
|
|
|
13
13
|
import { absoluteFill } from "../../../utils/absoluteFill.js";
|
|
14
14
|
import { macOSColors } from "../../gameUI/constants/macOSDesignSystemColors.js";
|
|
15
15
|
import { X } from "../../../icons/lucide-icons.js";
|
|
16
|
-
import {
|
|
16
|
+
import { monoFont } from "../../fonts.js";
|
|
17
17
|
/**
|
|
18
18
|
* EventPickerModal displays a modal for selecting events
|
|
19
19
|
* with color-coded styling based on position (left/right).
|
|
20
20
|
*/
|
|
21
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
21
22
|
export const EventPickerModal = /*#__PURE__*/memo(function EventPickerModal({
|
|
22
23
|
isOpen,
|
|
23
24
|
onClose,
|
|
@@ -118,7 +119,7 @@ const styles = StyleSheet.create({
|
|
|
118
119
|
title: {
|
|
119
120
|
fontSize: 13,
|
|
120
121
|
fontWeight: "700",
|
|
121
|
-
fontFamily:
|
|
122
|
+
fontFamily: monoFont,
|
|
122
123
|
textTransform: "uppercase",
|
|
123
124
|
marginBottom: 8,
|
|
124
125
|
letterSpacing: 0.6
|
|
@@ -185,18 +186,18 @@ const styles = StyleSheet.create({
|
|
|
185
186
|
itemIndex: {
|
|
186
187
|
fontSize: 10,
|
|
187
188
|
color: macOSColors.text.secondary,
|
|
188
|
-
fontFamily:
|
|
189
|
+
fontFamily: monoFont,
|
|
189
190
|
width: 40
|
|
190
191
|
},
|
|
191
192
|
itemTime: {
|
|
192
193
|
fontSize: 11,
|
|
193
194
|
color: macOSColors.text.primary,
|
|
194
|
-
fontFamily:
|
|
195
|
+
fontFamily: monoFont,
|
|
195
196
|
flex: 1
|
|
196
197
|
},
|
|
197
198
|
itemRelative: {
|
|
198
199
|
fontSize: 10,
|
|
199
200
|
color: macOSColors.text.secondary,
|
|
200
|
-
fontFamily:
|
|
201
|
+
fontFamily: monoFont
|
|
201
202
|
}
|
|
202
203
|
});
|
|
@@ -14,6 +14,7 @@ import { ChevronLeft, ChevronRight } from "../../icons/lucide-icons.js";
|
|
|
14
14
|
import { macOSColors } from "../gameUI/constants/macOSDesignSystemColors.js";
|
|
15
15
|
import { night } from "../night/nightTheme.js";
|
|
16
16
|
import { useSafeAreaInsets } from "../../hooks/useSafeAreaInsets.js";
|
|
17
|
+
import { monoFont } from "../fonts.js";
|
|
17
18
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
18
19
|
/**
|
|
19
20
|
* A footer component for navigating through a list of events/items.
|
|
@@ -132,7 +133,7 @@ const styles = StyleSheet.create({
|
|
|
132
133
|
fontSize: 12,
|
|
133
134
|
fontWeight: "600",
|
|
134
135
|
color: macOSColors.text.primary,
|
|
135
|
-
fontFamily:
|
|
136
|
+
fontFamily: monoFont,
|
|
136
137
|
textTransform: "uppercase"
|
|
137
138
|
},
|
|
138
139
|
navButtonTextDisabled: {
|
|
@@ -145,13 +146,13 @@ const styles = StyleSheet.create({
|
|
|
145
146
|
fontSize: 14,
|
|
146
147
|
fontWeight: "700",
|
|
147
148
|
color: macOSColors.text.primary,
|
|
148
|
-
fontFamily:
|
|
149
|
+
fontFamily: monoFont,
|
|
149
150
|
textTransform: "uppercase"
|
|
150
151
|
},
|
|
151
152
|
subtitleText: {
|
|
152
153
|
fontSize: 11,
|
|
153
154
|
color: macOSColors.text.secondary,
|
|
154
|
-
fontFamily:
|
|
155
|
+
fontFamily: monoFont,
|
|
155
156
|
marginTop: 2
|
|
156
157
|
},
|
|
157
158
|
// ── Night variant (see ui/night/nightTheme.ts): near-black glass bar with
|
|
@@ -28,7 +28,9 @@ function CollapsedPeek({
|
|
|
28
28
|
width,
|
|
29
29
|
height,
|
|
30
30
|
customContent,
|
|
31
|
-
label
|
|
31
|
+
label,
|
|
32
|
+
testID,
|
|
33
|
+
attention
|
|
32
34
|
}) {
|
|
33
35
|
// When progress=0 (collapsed): peek is visible (opacity=1, scale=1)
|
|
34
36
|
// When progress=1 (expanded): peek is hidden (opacity=0, scale=0.9)
|
|
@@ -48,16 +50,17 @@ function CollapsedPeek({
|
|
|
48
50
|
scale
|
|
49
51
|
}]
|
|
50
52
|
}],
|
|
51
|
-
children: /*#__PURE__*/
|
|
53
|
+
children: /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
52
54
|
onPress: onPress,
|
|
53
55
|
activeOpacity: 0.8,
|
|
54
56
|
style: [styles.peekButton, {
|
|
55
57
|
width,
|
|
56
58
|
height
|
|
57
59
|
}],
|
|
58
|
-
accessibilityLabel: label || `Expand options`,
|
|
60
|
+
accessibilityLabel: attention?.label ? `${label || "Expand options"} — ${attention.label}` : label || `Expand options`,
|
|
59
61
|
accessibilityRole: "button",
|
|
60
|
-
|
|
62
|
+
testID: testID,
|
|
63
|
+
children: [customContent || /*#__PURE__*/_jsxs(_Fragment, {
|
|
61
64
|
children: [/*#__PURE__*/_jsx(ChevronUp, {
|
|
62
65
|
size: 12,
|
|
63
66
|
color: buoyColors.textMuted,
|
|
@@ -66,7 +69,17 @@ function CollapsedPeek({
|
|
|
66
69
|
style: styles.peekCount,
|
|
67
70
|
children: count
|
|
68
71
|
})]
|
|
69
|
-
})
|
|
72
|
+
}), attention ? /*#__PURE__*/_jsx(View, {
|
|
73
|
+
pointerEvents: "none",
|
|
74
|
+
testID: testID ? `${testID}-attention` : undefined,
|
|
75
|
+
style: [styles.peekAttention, {
|
|
76
|
+
backgroundColor: attention.color
|
|
77
|
+
}],
|
|
78
|
+
children: attention.glyph ? /*#__PURE__*/_jsx(Text, {
|
|
79
|
+
style: styles.peekAttentionGlyph,
|
|
80
|
+
children: attention.glyph
|
|
81
|
+
}) : null
|
|
82
|
+
}) : null]
|
|
70
83
|
})
|
|
71
84
|
});
|
|
72
85
|
}
|
|
@@ -82,7 +95,8 @@ function ExpandedWrapper({
|
|
|
82
95
|
width,
|
|
83
96
|
expandedHeight,
|
|
84
97
|
isExpanded,
|
|
85
|
-
style
|
|
98
|
+
style,
|
|
99
|
+
collapseTestID
|
|
86
100
|
}) {
|
|
87
101
|
// Animate height from 0 to full height
|
|
88
102
|
const animatedHeight = progress.interpolate({
|
|
@@ -105,6 +119,7 @@ function ExpandedWrapper({
|
|
|
105
119
|
style: styles.collapseButton,
|
|
106
120
|
accessibilityLabel: "Collapse",
|
|
107
121
|
accessibilityRole: "button",
|
|
122
|
+
testID: collapseTestID,
|
|
108
123
|
children: /*#__PURE__*/_jsx(ChevronUp, {
|
|
109
124
|
size: 12,
|
|
110
125
|
color: buoyColors.textMuted,
|
|
@@ -134,10 +149,13 @@ export function ExpandablePopover({
|
|
|
134
149
|
defaultExpanded = false,
|
|
135
150
|
collapsedContent,
|
|
136
151
|
collapsedLabel,
|
|
152
|
+
attention = null,
|
|
137
153
|
expandedStyle,
|
|
138
154
|
persistState = false,
|
|
139
155
|
storageKey,
|
|
140
|
-
peekHeight = DEFAULT_PEEK_HEIGHT
|
|
156
|
+
peekHeight = DEFAULT_PEEK_HEIGHT,
|
|
157
|
+
testID,
|
|
158
|
+
collapseTestID
|
|
141
159
|
}) {
|
|
142
160
|
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
|
|
143
161
|
const [isStateRestored, setIsStateRestored] = useState(!persistState);
|
|
@@ -240,6 +258,7 @@ export function ExpandablePopover({
|
|
|
240
258
|
style: styles.expandedWrapper,
|
|
241
259
|
pointerEvents: isExpanded ? "box-none" : "none",
|
|
242
260
|
children: /*#__PURE__*/_jsx(ExpandedWrapper, {
|
|
261
|
+
collapseTestID: collapseTestID,
|
|
243
262
|
onCollapse: handleCollapse,
|
|
244
263
|
progress: progress,
|
|
245
264
|
width: width,
|
|
@@ -259,7 +278,9 @@ export function ExpandablePopover({
|
|
|
259
278
|
width: width,
|
|
260
279
|
height: peekHeight,
|
|
261
280
|
customContent: collapsedContent,
|
|
262
|
-
label: collapsedLabel
|
|
281
|
+
label: collapsedLabel,
|
|
282
|
+
testID: testID,
|
|
283
|
+
attention: attention
|
|
263
284
|
})
|
|
264
285
|
})]
|
|
265
286
|
});
|
|
@@ -270,6 +291,25 @@ export function ExpandablePopover({
|
|
|
270
291
|
// ============================================================================
|
|
271
292
|
|
|
272
293
|
const styles = StyleSheet.create({
|
|
294
|
+
peekAttention: {
|
|
295
|
+
position: "absolute",
|
|
296
|
+
top: 2,
|
|
297
|
+
right: 2,
|
|
298
|
+
minWidth: 11,
|
|
299
|
+
height: 11,
|
|
300
|
+
borderRadius: 6,
|
|
301
|
+
paddingHorizontal: 2,
|
|
302
|
+
alignItems: "center",
|
|
303
|
+
justifyContent: "center",
|
|
304
|
+
borderWidth: 1.5,
|
|
305
|
+
borderColor: "#0C0C0C"
|
|
306
|
+
},
|
|
307
|
+
peekAttentionGlyph: {
|
|
308
|
+
color: "#000",
|
|
309
|
+
fontSize: 8,
|
|
310
|
+
fontWeight: "800",
|
|
311
|
+
lineHeight: 9
|
|
312
|
+
},
|
|
273
313
|
container: {
|
|
274
314
|
overflow: "visible",
|
|
275
315
|
zIndex: 1000
|