@buoy-gg/shared-ui 7.0.4 → 7.0.6
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/colors/index.js +49 -0
- package/lib/commonjs/dataViewer/DataTreeActionBar.js +389 -0
- package/lib/commonjs/dataViewer/DataTreeActionDock.js +222 -0
- package/lib/commonjs/dataViewer/DataViewer.js +18 -3
- package/lib/commonjs/dataViewer/VirtualizedDataExplorer.js +227 -28
- package/lib/commonjs/dataViewer/index.js +88 -0
- package/lib/commonjs/dataViewer/jsonOps.js +320 -0
- package/lib/commonjs/dataViewer/lineDiff.js +285 -83
- package/lib/commonjs/dataViewer/tree/TreeDiffViewer.js +20 -5
- package/lib/commonjs/dataViewer/treeActions.js +167 -0
- package/lib/commonjs/env/EnvironmentSelector.js +2 -2
- package/lib/commonjs/env/EnvironmentSelectorInline.js +2 -2
- package/lib/commonjs/hooks/safe-area-impl.js +1 -1
- package/lib/commonjs/icons/index.js +79 -3
- package/lib/commonjs/icons/lucide-icons-original-full.js +5 -1
- package/lib/commonjs/icons/lucide-icons.js +59 -2
- package/lib/commonjs/index.js +35 -0
- package/lib/commonjs/settings/components/BubbleSettingsSection.js +21 -19
- package/lib/commonjs/storage/devToolsStorageKeys.js +6 -3
- package/lib/commonjs/ui/components/Badge.js +2 -0
- package/lib/commonjs/ui/components/CompactRow.js +7 -0
- package/lib/commonjs/ui/components/CopyButton.js +27 -4
- package/lib/commonjs/ui/components/DevToolsCard.js +11 -0
- package/lib/commonjs/ui/components/DynamicFilterView.js +8 -1
- package/lib/commonjs/ui/components/EmptyState.js +12 -5
- package/lib/commonjs/ui/components/ErrorBoundary.js +3 -2
- package/lib/commonjs/ui/components/EventHistoryViewer/EventHistoryViewer.js +63 -11
- package/lib/commonjs/ui/components/ExpandableSection.js +4 -3
- package/lib/commonjs/ui/components/ExpandableSectionHeader.js +2 -1
- package/lib/commonjs/ui/components/FilterViewPattern.js +8 -7
- package/lib/commonjs/ui/components/ListItem.js +7 -5
- package/lib/commonjs/ui/components/PowerToggleButton.js +4 -1
- package/lib/commonjs/ui/components/TabSelector.js +3 -0
- package/lib/commonjs/ui/console/CyberpunkConsoleSection.js +1 -1
- package/lib/commonjs/ui/console/GalaxyButton.js +1 -1
- package/lib/commonjs/ui/gameUI/components/GameUICompactStats.js +2 -2
- package/lib/commonjs/ui/gameUI/constants/gameUIColors.js +28 -6
- package/lib/commonjs/ui/gameUI/constants/macOSDesignSystemColors.js +22 -4
- package/lib/commonjs/utils/index.js +25 -0
- package/lib/commonjs/utils/reloadApp.js +144 -0
- package/lib/module/colors/index.js +21 -0
- package/lib/module/dataViewer/DataTreeActionBar.js +384 -0
- package/lib/module/dataViewer/DataTreeActionDock.js +218 -0
- package/lib/module/dataViewer/DataViewer.js +18 -3
- package/lib/module/dataViewer/VirtualizedDataExplorer.js +228 -30
- package/lib/module/dataViewer/index.js +16 -1
- package/lib/module/dataViewer/jsonOps.js +311 -0
- package/lib/module/dataViewer/lineDiff.js +284 -82
- package/lib/module/dataViewer/tree/TreeDiffViewer.js +20 -5
- package/lib/module/dataViewer/treeActions.js +161 -0
- package/lib/module/env/EnvironmentSelector.js +2 -2
- package/lib/module/env/EnvironmentSelectorInline.js +2 -2
- package/lib/module/hooks/safe-area-impl.js +1 -1
- package/lib/module/icons/index.js +10 -1
- package/lib/module/icons/lucide-icons-original-full.js +5 -1
- package/lib/module/icons/lucide-icons.js +56 -0
- package/lib/module/index.js +4 -0
- package/lib/module/settings/components/BubbleSettingsSection.js +21 -19
- package/lib/module/storage/devToolsStorageKeys.js +6 -3
- package/lib/module/ui/components/Badge.js +2 -0
- package/lib/module/ui/components/CompactRow.js +7 -0
- package/lib/module/ui/components/CopyButton.js +29 -6
- package/lib/module/ui/components/DevToolsCard.js +11 -0
- package/lib/module/ui/components/DynamicFilterView.js +8 -1
- package/lib/module/ui/components/EmptyState.js +12 -5
- package/lib/module/ui/components/ErrorBoundary.js +3 -2
- package/lib/module/ui/components/EventHistoryViewer/EventHistoryViewer.js +63 -11
- package/lib/module/ui/components/ExpandableSection.js +4 -3
- package/lib/module/ui/components/ExpandableSectionHeader.js +2 -1
- package/lib/module/ui/components/FilterViewPattern.js +9 -7
- package/lib/module/ui/components/ListItem.js +7 -5
- package/lib/module/ui/components/PowerToggleButton.js +4 -1
- package/lib/module/ui/components/TabSelector.js +3 -0
- package/lib/module/ui/console/CyberpunkConsoleSection.js +1 -1
- package/lib/module/ui/console/GalaxyButton.js +1 -1
- package/lib/module/ui/gameUI/components/GameUICompactStats.js +2 -2
- package/lib/module/ui/gameUI/constants/gameUIColors.js +27 -6
- package/lib/module/ui/gameUI/constants/macOSDesignSystemColors.js +19 -2
- package/lib/module/utils/index.js +1 -0
- package/lib/module/utils/reloadApp.js +137 -0
- package/lib/typescript/commonjs/colors/index.d.ts +22 -0
- package/lib/typescript/commonjs/colors/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/dataViewer/DataTreeActionBar.d.ts +53 -0
- package/lib/typescript/commonjs/dataViewer/DataTreeActionBar.d.ts.map +1 -0
- package/lib/typescript/commonjs/dataViewer/DataTreeActionDock.d.ts +33 -0
- package/lib/typescript/commonjs/dataViewer/DataTreeActionDock.d.ts.map +1 -0
- package/lib/typescript/commonjs/dataViewer/DataViewer.d.ts +14 -1
- package/lib/typescript/commonjs/dataViewer/DataViewer.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/VirtualizedDataExplorer.d.ts +30 -1
- package/lib/typescript/commonjs/dataViewer/VirtualizedDataExplorer.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/__tests__/jsonOps.test.d.ts +19 -0
- package/lib/typescript/commonjs/dataViewer/__tests__/jsonOps.test.d.ts.map +1 -0
- package/lib/typescript/commonjs/dataViewer/index.d.ts +5 -1
- package/lib/typescript/commonjs/dataViewer/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/jsonOps.d.ts +124 -0
- package/lib/typescript/commonjs/dataViewer/jsonOps.d.ts.map +1 -0
- package/lib/typescript/commonjs/dataViewer/lineDiff.d.ts +27 -0
- package/lib/typescript/commonjs/dataViewer/lineDiff.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/tree/TreeDiffViewer.d.ts +8 -1
- package/lib/typescript/commonjs/dataViewer/tree/TreeDiffViewer.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/treeActions.d.ts +83 -0
- package/lib/typescript/commonjs/dataViewer/treeActions.d.ts.map +1 -0
- package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/commonjs/icons/index.d.ts +6 -1
- package/lib/typescript/commonjs/icons/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/icons/lucide-icons-original-full.d.ts.map +1 -1
- package/lib/typescript/commonjs/icons/lucide-icons.d.ts +9 -0
- package/lib/typescript/commonjs/icons/lucide-icons.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +2 -1
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/settings/components/BubbleSettingsSection.d.ts.map +1 -1
- package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts +5 -1
- package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/CopyButton.d.ts +7 -1
- package/lib/typescript/commonjs/ui/components/CopyButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/EmptyState.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ErrorBoundary.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/EventHistoryViewer/EventHistoryViewer.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/EventHistoryViewer/types.d.ts +23 -7
- package/lib/typescript/commonjs/ui/components/EventHistoryViewer/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ExpandableSection.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ExpandableSectionHeader.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/FilterViewPattern.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ListItem.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/gameUI/constants/gameUIColors.d.ts +36 -30
- package/lib/typescript/commonjs/ui/gameUI/constants/gameUIColors.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/gameUI/constants/macOSDesignSystemColors.d.ts +5 -0
- package/lib/typescript/commonjs/ui/gameUI/constants/macOSDesignSystemColors.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/index.d.ts +1 -0
- package/lib/typescript/commonjs/utils/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/reloadApp.d.ts +68 -0
- package/lib/typescript/commonjs/utils/reloadApp.d.ts.map +1 -0
- package/lib/typescript/module/colors/index.d.ts +22 -0
- package/lib/typescript/module/colors/index.d.ts.map +1 -0
- package/lib/typescript/module/dataViewer/DataTreeActionBar.d.ts +53 -0
- package/lib/typescript/module/dataViewer/DataTreeActionBar.d.ts.map +1 -0
- package/lib/typescript/module/dataViewer/DataTreeActionDock.d.ts +33 -0
- package/lib/typescript/module/dataViewer/DataTreeActionDock.d.ts.map +1 -0
- package/lib/typescript/module/dataViewer/DataViewer.d.ts +14 -1
- package/lib/typescript/module/dataViewer/DataViewer.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/VirtualizedDataExplorer.d.ts +30 -1
- package/lib/typescript/module/dataViewer/VirtualizedDataExplorer.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/__tests__/jsonOps.test.d.ts +19 -0
- package/lib/typescript/module/dataViewer/__tests__/jsonOps.test.d.ts.map +1 -0
- package/lib/typescript/module/dataViewer/index.d.ts +5 -1
- package/lib/typescript/module/dataViewer/index.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/jsonOps.d.ts +124 -0
- package/lib/typescript/module/dataViewer/jsonOps.d.ts.map +1 -0
- package/lib/typescript/module/dataViewer/lineDiff.d.ts +27 -0
- package/lib/typescript/module/dataViewer/lineDiff.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/tree/TreeDiffViewer.d.ts +8 -1
- package/lib/typescript/module/dataViewer/tree/TreeDiffViewer.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/treeActions.d.ts +83 -0
- package/lib/typescript/module/dataViewer/treeActions.d.ts.map +1 -0
- package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/module/icons/index.d.ts +6 -1
- package/lib/typescript/module/icons/index.d.ts.map +1 -1
- package/lib/typescript/module/icons/lucide-icons-original-full.d.ts.map +1 -1
- package/lib/typescript/module/icons/lucide-icons.d.ts +9 -0
- package/lib/typescript/module/icons/lucide-icons.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +2 -1
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/settings/components/BubbleSettingsSection.d.ts.map +1 -1
- package/lib/typescript/module/storage/devToolsStorageKeys.d.ts +5 -1
- package/lib/typescript/module/storage/devToolsStorageKeys.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/CopyButton.d.ts +7 -1
- package/lib/typescript/module/ui/components/CopyButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/EmptyState.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ErrorBoundary.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/EventHistoryViewer/EventHistoryViewer.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/EventHistoryViewer/types.d.ts +23 -7
- package/lib/typescript/module/ui/components/EventHistoryViewer/types.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ExpandableSection.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ExpandableSectionHeader.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/FilterViewPattern.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ListItem.d.ts.map +1 -1
- package/lib/typescript/module/ui/gameUI/constants/gameUIColors.d.ts +36 -30
- package/lib/typescript/module/ui/gameUI/constants/gameUIColors.d.ts.map +1 -1
- package/lib/typescript/module/ui/gameUI/constants/macOSDesignSystemColors.d.ts +5 -0
- package/lib/typescript/module/ui/gameUI/constants/macOSDesignSystemColors.d.ts.map +1 -1
- package/lib/typescript/module/utils/index.d.ts +1 -0
- package/lib/typescript/module/utils/index.d.ts.map +1 -1
- package/lib/typescript/module/utils/reloadApp.d.ts +68 -0
- package/lib/typescript/module/utils/reloadApp.d.ts.map +1 -0
- package/package.json +15 -4
- package/lib/commonjs/icons/ImageOverlayIcon.js +0 -142
- package/lib/module/icons/ImageOverlayIcon.js +0 -137
- package/lib/typescript/commonjs/icons/ImageOverlayIcon.d.ts +0 -14
- package/lib/typescript/commonjs/icons/ImageOverlayIcon.d.ts.map +0 -1
- package/lib/typescript/module/icons/ImageOverlayIcon.d.ts +0 -14
- package/lib/typescript/module/icons/ImageOverlayIcon.d.ts.map +0 -1
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.DiffType = void 0;
|
|
6
|
+
exports.DiffType = exports.ABSENT_VALUE = void 0;
|
|
7
7
|
exports.computeLineDiff = computeLineDiff;
|
|
8
|
+
exports.isAbsent = isAbsent;
|
|
8
9
|
/**
|
|
9
10
|
* Line-by-line diff computation for React Native
|
|
10
11
|
*
|
|
@@ -18,6 +19,23 @@ let DiffType = exports.DiffType = /*#__PURE__*/function (DiffType) {
|
|
|
18
19
|
DiffType["MODIFIED"] = "modified";
|
|
19
20
|
return DiffType;
|
|
20
21
|
}({});
|
|
22
|
+
/**
|
|
23
|
+
* Marks one side of a diff as "this value did not exist".
|
|
24
|
+
*
|
|
25
|
+
* Deliberately distinct from `null`, `[]`, `{}` and `""` — those are real
|
|
26
|
+
* stored values and diff normally. An absent side contributes zero lines, so a
|
|
27
|
+
* key that was just created reads as purely added rather than as an edit of the
|
|
28
|
+
* literal text `null`.
|
|
29
|
+
*
|
|
30
|
+
* `Symbol.for` so the identity holds even if a bundler ends up with two copies
|
|
31
|
+
* of this module.
|
|
32
|
+
*/
|
|
33
|
+
const ABSENT_VALUE = exports.ABSENT_VALUE = Symbol.for("buoy.diff.absent");
|
|
34
|
+
|
|
35
|
+
/** True when a diff side represents a value that did not exist. */
|
|
36
|
+
function isAbsent(value) {
|
|
37
|
+
return value === ABSENT_VALUE;
|
|
38
|
+
}
|
|
21
39
|
/**
|
|
22
40
|
* Compute diff based on method - for word-level diff within lines
|
|
23
41
|
*/
|
|
@@ -157,6 +175,10 @@ function computeDiffByMethod(oldStr, newStr, method) {
|
|
|
157
175
|
* Convert object to formatted JSON lines
|
|
158
176
|
*/
|
|
159
177
|
function objectToLines(obj) {
|
|
178
|
+
// A value that never existed has no text at all — not the word "null".
|
|
179
|
+
if (isAbsent(obj)) {
|
|
180
|
+
return [];
|
|
181
|
+
}
|
|
160
182
|
if (obj === null || obj === undefined) {
|
|
161
183
|
return [String(obj)];
|
|
162
184
|
}
|
|
@@ -240,63 +262,265 @@ function filterDiffWithContext(diffs, contextLines) {
|
|
|
240
262
|
}
|
|
241
263
|
|
|
242
264
|
/**
|
|
243
|
-
*
|
|
265
|
+
* Normalize a line into the key used for matching.
|
|
266
|
+
*
|
|
267
|
+
* Display always uses the raw JSON; only matching sees this. `trimmedLines`
|
|
268
|
+
* drops indentation, and `ignoreTrailingComma` drops the trailing comma so
|
|
269
|
+
* pushing one item onto an array doesn't report the previous last item as
|
|
270
|
+
* modified.
|
|
244
271
|
*/
|
|
245
|
-
function
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
272
|
+
function normalizeCompareKey(line, compareMethod, ignoreTrailingComma) {
|
|
273
|
+
const base = compareMethod === "trimmedLines" ? line.trim() : line;
|
|
274
|
+
return ignoreTrailingComma ? base.replace(/,\s*$/, "") : base;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* The original heuristic: lines that start alike are an edit of one line rather
|
|
279
|
+
* than an unrelated removal plus addition. Only ever applied inside a hunk the
|
|
280
|
+
* line matcher already proved unmatched, so it can no longer pair lines that
|
|
281
|
+
* merely shifted position.
|
|
282
|
+
*/
|
|
283
|
+
function looksLikeModification(oldLine, newLine) {
|
|
284
|
+
const oldTrimmed = oldLine.trim();
|
|
285
|
+
const newTrimmed = newLine.trim();
|
|
286
|
+
return !!oldTrimmed && !!newTrimmed && (oldTrimmed.startsWith(newTrimmed.substring(0, 3)) || newTrimmed.startsWith(oldTrimmed.substring(0, 3)));
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Myers is O(ND) in the number of edits, so near-identical values (the common
|
|
290
|
+
* case — one array push) are close to free and only wildly different values get
|
|
291
|
+
* expensive. Past these bounds we fall back to the pairwise walk.
|
|
292
|
+
*/
|
|
293
|
+
const MYERS_MAX_TOTAL_LINES = 8000;
|
|
294
|
+
const MYERS_MAX_EDIT_DISTANCE = 1024;
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Myers' O(ND) diff ("An O(ND) Difference Algorithm and Its Variations", 1986)
|
|
298
|
+
* over line keys — the same algorithm git and `diff` use.
|
|
299
|
+
*
|
|
300
|
+
* Returns null when the input is too large or too dissimilar to be worth it,
|
|
301
|
+
* which tells the caller to use the fallback walk.
|
|
302
|
+
*/
|
|
303
|
+
function myersLineOps(a, b) {
|
|
304
|
+
const n = a.length;
|
|
305
|
+
const m = b.length;
|
|
306
|
+
if (n + m > MYERS_MAX_TOTAL_LINES) return null;
|
|
307
|
+
if (n === 0 && m === 0) return [];
|
|
308
|
+
const max = n + m;
|
|
309
|
+
// +1 of padding on each side so the k-1 / k+1 probes at the frontier stay in
|
|
310
|
+
// bounds without clamping (clamping would corrupt the index arithmetic).
|
|
311
|
+
const offset = max + 1;
|
|
312
|
+
const v = new Int32Array(2 * max + 3);
|
|
313
|
+
const maxD = Math.min(max, MYERS_MAX_EDIT_DISTANCE);
|
|
314
|
+
|
|
315
|
+
// Frontier snapshot per depth. Only k in [-(d+1), d+1] is ever read back, so
|
|
316
|
+
// each snapshot is O(d) and the whole trace is O(D^2) — not O(D * max).
|
|
317
|
+
const trace = [];
|
|
318
|
+
for (let d = 0; d <= maxD; d++) {
|
|
319
|
+
trace.push(v.slice(offset - (d + 1), offset + d + 2));
|
|
320
|
+
for (let k = -d; k <= d; k += 2) {
|
|
321
|
+
let x;
|
|
322
|
+
if (k === -d || k !== d && v[k - 1 + offset] < v[k + 1 + offset]) {
|
|
323
|
+
x = v[k + 1 + offset];
|
|
324
|
+
} else {
|
|
325
|
+
x = v[k - 1 + offset] + 1;
|
|
326
|
+
}
|
|
327
|
+
let y = x - k;
|
|
328
|
+
|
|
329
|
+
// Follow the diagonal as far as the lines keep matching.
|
|
330
|
+
while (x < n && y < m && a[x] === b[y]) {
|
|
331
|
+
x++;
|
|
332
|
+
y++;
|
|
333
|
+
}
|
|
334
|
+
v[k + offset] = x;
|
|
335
|
+
if (x >= n && y >= m) {
|
|
336
|
+
return backtrackOps(trace, n, m);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
254
339
|
}
|
|
340
|
+
return null;
|
|
255
341
|
}
|
|
256
342
|
|
|
257
343
|
/**
|
|
258
|
-
*
|
|
344
|
+
* Walk the recorded frontiers backwards to recover the edit script.
|
|
259
345
|
*/
|
|
260
|
-
function
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
346
|
+
function backtrackOps(trace, n, m) {
|
|
347
|
+
const ops = [];
|
|
348
|
+
let x = n;
|
|
349
|
+
let y = m;
|
|
350
|
+
for (let d = trace.length - 1; d >= 0; d--) {
|
|
351
|
+
const snapshot = trace[d];
|
|
352
|
+
// Snapshot d covers k in [-(d+1), d+1], so k=0 sits at index d+1.
|
|
353
|
+
const base = d + 1;
|
|
354
|
+
const k = x - y;
|
|
355
|
+
let prevK;
|
|
356
|
+
if (k === -d || k !== d && snapshot[k - 1 + base] < snapshot[k + 1 + base]) {
|
|
357
|
+
prevK = k + 1;
|
|
358
|
+
} else {
|
|
359
|
+
prevK = k - 1;
|
|
360
|
+
}
|
|
361
|
+
const prevX = snapshot[prevK + base];
|
|
362
|
+
const prevY = prevX - prevK;
|
|
363
|
+
while (x > prevX && y > prevY) {
|
|
364
|
+
ops.push({
|
|
365
|
+
kind: "eq",
|
|
366
|
+
i: x - 1,
|
|
367
|
+
j: y - 1
|
|
368
|
+
});
|
|
369
|
+
x--;
|
|
370
|
+
y--;
|
|
371
|
+
}
|
|
372
|
+
if (d > 0) {
|
|
373
|
+
if (x === prevX) {
|
|
374
|
+
ops.push({
|
|
375
|
+
kind: "ins",
|
|
376
|
+
j: y - 1
|
|
377
|
+
});
|
|
378
|
+
} else {
|
|
379
|
+
ops.push({
|
|
380
|
+
kind: "del",
|
|
381
|
+
i: x - 1
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
x = prevX;
|
|
386
|
+
y = prevY;
|
|
387
|
+
}
|
|
388
|
+
ops.reverse();
|
|
389
|
+
return ops;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Emit one hunk of unmatched lines. Removals and additions are paired off in
|
|
394
|
+
* order and become MODIFIED rows when they look like an edit of the same line;
|
|
395
|
+
* everything left over stays a one-sided removal or addition.
|
|
396
|
+
*/
|
|
397
|
+
function emitHunk(result, dels, inss, oldLines, newLines, compareMethod, disableWordDiff) {
|
|
398
|
+
const pairs = Math.min(dels.length, inss.length);
|
|
399
|
+
for (let k = 0; k < pairs; k++) {
|
|
400
|
+
const i = dels[k];
|
|
401
|
+
const j = inss[k];
|
|
402
|
+
if (!looksLikeModification(oldLines[i], newLines[j])) {
|
|
403
|
+
result.push({
|
|
404
|
+
leftLineNumber: i + 1,
|
|
405
|
+
type: DiffType.REMOVED,
|
|
406
|
+
leftContent: oldLines[i],
|
|
407
|
+
leftRaw: oldLines[i]
|
|
408
|
+
});
|
|
409
|
+
result.push({
|
|
410
|
+
rightLineNumber: j + 1,
|
|
411
|
+
type: DiffType.ADDED,
|
|
412
|
+
rightContent: newLines[j],
|
|
413
|
+
rightRaw: newLines[j]
|
|
414
|
+
});
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
if (!disableWordDiff && compareMethod !== "lines") {
|
|
418
|
+
const wordDiff = computeDiffByMethod(oldLines[i], newLines[j], compareMethod);
|
|
419
|
+
result.push({
|
|
420
|
+
leftLineNumber: i + 1,
|
|
421
|
+
rightLineNumber: j + 1,
|
|
422
|
+
type: DiffType.MODIFIED,
|
|
423
|
+
leftContent: wordDiff.left,
|
|
424
|
+
rightContent: wordDiff.right,
|
|
425
|
+
leftRaw: oldLines[i],
|
|
426
|
+
rightRaw: newLines[j]
|
|
427
|
+
});
|
|
428
|
+
} else {
|
|
429
|
+
result.push({
|
|
430
|
+
leftLineNumber: i + 1,
|
|
431
|
+
rightLineNumber: j + 1,
|
|
432
|
+
type: DiffType.MODIFIED,
|
|
433
|
+
leftContent: oldLines[i],
|
|
434
|
+
rightContent: newLines[j],
|
|
435
|
+
leftRaw: oldLines[i],
|
|
436
|
+
rightRaw: newLines[j]
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
for (let k = pairs; k < dels.length; k++) {
|
|
441
|
+
const i = dels[k];
|
|
442
|
+
result.push({
|
|
443
|
+
leftLineNumber: i + 1,
|
|
444
|
+
type: DiffType.REMOVED,
|
|
445
|
+
leftContent: oldLines[i],
|
|
446
|
+
leftRaw: oldLines[i]
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
for (let k = pairs; k < inss.length; k++) {
|
|
450
|
+
const j = inss[k];
|
|
451
|
+
result.push({
|
|
452
|
+
rightLineNumber: j + 1,
|
|
453
|
+
type: DiffType.ADDED,
|
|
454
|
+
rightContent: newLines[j],
|
|
455
|
+
rightRaw: newLines[j]
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Turn the edit script into rows, grouping each run of unmatched lines into a
|
|
462
|
+
* hunk so modification pairing stays local to a real change.
|
|
463
|
+
*/
|
|
464
|
+
function buildRowsFromOps(ops, oldLines, newLines, compareMethod, disableWordDiff) {
|
|
269
465
|
const result = [];
|
|
270
|
-
let
|
|
271
|
-
|
|
466
|
+
let idx = 0;
|
|
467
|
+
while (idx < ops.length) {
|
|
468
|
+
const op = ops[idx];
|
|
469
|
+
if (op.kind === "eq") {
|
|
470
|
+
result.push({
|
|
471
|
+
leftLineNumber: op.i + 1,
|
|
472
|
+
rightLineNumber: op.j + 1,
|
|
473
|
+
type: DiffType.DEFAULT,
|
|
474
|
+
leftContent: oldLines[op.i],
|
|
475
|
+
rightContent: newLines[op.j],
|
|
476
|
+
leftRaw: oldLines[op.i],
|
|
477
|
+
rightRaw: newLines[op.j]
|
|
478
|
+
});
|
|
479
|
+
idx++;
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
482
|
+
const dels = [];
|
|
483
|
+
const inss = [];
|
|
484
|
+
while (idx < ops.length && ops[idx].kind !== "eq") {
|
|
485
|
+
const hunkOp = ops[idx];
|
|
486
|
+
if (hunkOp.kind === "del") dels.push(hunkOp.i);else if (hunkOp.kind === "ins") inss.push(hunkOp.j);
|
|
487
|
+
idx++;
|
|
488
|
+
}
|
|
489
|
+
emitHunk(result, dels, inss, oldLines, newLines, compareMethod, disableWordDiff);
|
|
490
|
+
}
|
|
491
|
+
return result;
|
|
492
|
+
}
|
|
272
493
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
494
|
+
/**
|
|
495
|
+
* Fallback pairwise walk, used only when the input is past the Myers bounds.
|
|
496
|
+
* Advances both sides in lockstep, so a shifted line reads as changed — the
|
|
497
|
+
* reason it isn't the primary path.
|
|
498
|
+
*/
|
|
499
|
+
function pairwiseLineWalk(oldLines, newLines, oldKeys, newKeys, compareMethod, disableWordDiff) {
|
|
500
|
+
const result = [];
|
|
501
|
+
let i = 0;
|
|
502
|
+
let j = 0;
|
|
276
503
|
while (i < oldLines.length || j < newLines.length) {
|
|
277
504
|
if (i >= oldLines.length) {
|
|
278
|
-
// Rest are additions
|
|
279
505
|
result.push({
|
|
280
|
-
rightLineNumber:
|
|
506
|
+
rightLineNumber: j + 1,
|
|
281
507
|
type: DiffType.ADDED,
|
|
282
508
|
rightContent: newLines[j],
|
|
283
509
|
rightRaw: newLines[j]
|
|
284
510
|
});
|
|
285
511
|
j++;
|
|
286
512
|
} else if (j >= newLines.length) {
|
|
287
|
-
// Rest are removals
|
|
288
513
|
result.push({
|
|
289
|
-
leftLineNumber:
|
|
514
|
+
leftLineNumber: i + 1,
|
|
290
515
|
type: DiffType.REMOVED,
|
|
291
516
|
leftContent: oldLines[i],
|
|
292
517
|
leftRaw: oldLines[i]
|
|
293
518
|
});
|
|
294
519
|
i++;
|
|
295
|
-
} else if (
|
|
296
|
-
// Lines match (possibly after trimming if trimmedLines)
|
|
520
|
+
} else if (oldKeys[i] === newKeys[j]) {
|
|
297
521
|
result.push({
|
|
298
|
-
leftLineNumber:
|
|
299
|
-
rightLineNumber:
|
|
522
|
+
leftLineNumber: i + 1,
|
|
523
|
+
rightLineNumber: j + 1,
|
|
300
524
|
type: DiffType.DEFAULT,
|
|
301
525
|
leftContent: oldLines[i],
|
|
302
526
|
rightContent: newLines[j],
|
|
@@ -306,57 +530,35 @@ function computeLineDiff(oldValue, newValue, options = {}) {
|
|
|
306
530
|
i++;
|
|
307
531
|
j++;
|
|
308
532
|
} else {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
// Simple heuristic: if lines start similarly, treat as modification
|
|
314
|
-
if (oldTrimmed && newTrimmed && (oldTrimmed.startsWith(newTrimmed.substring(0, 3)) || newTrimmed.startsWith(oldTrimmed.substring(0, 3)))) {
|
|
315
|
-
// Treat as modification - compute word diff if enabled
|
|
316
|
-
if (!disableWordDiff && compareMethod !== "lines") {
|
|
317
|
-
const wordDiff = computeDiffByMethod(oldLines[i], newLines[j], compareMethod);
|
|
318
|
-
result.push({
|
|
319
|
-
leftLineNumber: leftLineNum++,
|
|
320
|
-
rightLineNumber: rightLineNum++,
|
|
321
|
-
type: DiffType.MODIFIED,
|
|
322
|
-
leftContent: wordDiff.left,
|
|
323
|
-
rightContent: wordDiff.right,
|
|
324
|
-
leftRaw: oldLines[i],
|
|
325
|
-
rightRaw: newLines[j]
|
|
326
|
-
});
|
|
327
|
-
} else {
|
|
328
|
-
// No word diff - just mark lines as different
|
|
329
|
-
result.push({
|
|
330
|
-
leftLineNumber: leftLineNum++,
|
|
331
|
-
rightLineNumber: rightLineNum++,
|
|
332
|
-
type: DiffType.MODIFIED,
|
|
333
|
-
leftContent: oldLines[i],
|
|
334
|
-
rightContent: newLines[j],
|
|
335
|
-
leftRaw: oldLines[i],
|
|
336
|
-
rightRaw: newLines[j]
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
i++;
|
|
340
|
-
j++;
|
|
341
|
-
} else {
|
|
342
|
-
// Treat as separate remove and add
|
|
343
|
-
result.push({
|
|
344
|
-
leftLineNumber: leftLineNum++,
|
|
345
|
-
type: DiffType.REMOVED,
|
|
346
|
-
leftContent: oldLines[i],
|
|
347
|
-
leftRaw: oldLines[i]
|
|
348
|
-
});
|
|
349
|
-
result.push({
|
|
350
|
-
rightLineNumber: rightLineNum++,
|
|
351
|
-
type: DiffType.ADDED,
|
|
352
|
-
rightContent: newLines[j],
|
|
353
|
-
rightRaw: newLines[j]
|
|
354
|
-
});
|
|
355
|
-
i++;
|
|
356
|
-
j++;
|
|
357
|
-
}
|
|
533
|
+
emitHunk(result, [i], [j], oldLines, newLines, compareMethod, disableWordDiff);
|
|
534
|
+
i++;
|
|
535
|
+
j++;
|
|
358
536
|
}
|
|
359
537
|
}
|
|
538
|
+
return result;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Compute line-by-line diff between two objects
|
|
543
|
+
*
|
|
544
|
+
* Lines are matched with Myers' O(ND) algorithm over normalized keys, so an
|
|
545
|
+
* insert or append shows up as the one line that actually arrived instead of
|
|
546
|
+
* every line after it shifting into a change.
|
|
547
|
+
*/
|
|
548
|
+
function computeLineDiff(oldValue, newValue, options = {}) {
|
|
549
|
+
const {
|
|
550
|
+
compareMethod = "words",
|
|
551
|
+
disableWordDiff = false,
|
|
552
|
+
showDiffOnly = false,
|
|
553
|
+
contextLines = 3,
|
|
554
|
+
ignoreTrailingComma = true
|
|
555
|
+
} = options;
|
|
556
|
+
const oldLines = objectToLines(oldValue);
|
|
557
|
+
const newLines = objectToLines(newValue);
|
|
558
|
+
const oldKeys = oldLines.map(line => normalizeCompareKey(line, compareMethod, ignoreTrailingComma));
|
|
559
|
+
const newKeys = newLines.map(line => normalizeCompareKey(line, compareMethod, ignoreTrailingComma));
|
|
560
|
+
const ops = myersLineOps(oldKeys, newKeys);
|
|
561
|
+
const result = ops ? buildRowsFromOps(ops, oldLines, newLines, compareMethod, disableWordDiff) : pairwiseLineWalk(oldLines, newLines, oldKeys, newKeys, compareMethod, disableWordDiff);
|
|
360
562
|
|
|
361
563
|
// Apply showDiffOnly filter if enabled
|
|
362
564
|
if (showDiffOnly) {
|
|
@@ -7,6 +7,7 @@ exports.default = TreeDiffViewer;
|
|
|
7
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
9
|
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
10
|
+
var _lineDiff = require("../lineDiff.js");
|
|
10
11
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
11
12
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
12
13
|
// @ts-nocheck
|
|
@@ -110,6 +111,11 @@ function isEqual(a, b) {
|
|
|
110
111
|
function computeDiff(oldValue, newValue, path = []) {
|
|
111
112
|
const result = [];
|
|
112
113
|
|
|
114
|
+
// A side marked absent never existed, so it contributes nothing and the other
|
|
115
|
+
// side reads as purely added (or removed). Only the root can be absent.
|
|
116
|
+
if ((0, _lineDiff.isAbsent)(oldValue)) oldValue = undefined;
|
|
117
|
+
if ((0, _lineDiff.isAbsent)(newValue)) newValue = undefined;
|
|
118
|
+
|
|
113
119
|
// Handle primitives and null/undefined
|
|
114
120
|
if (!isObject(oldValue) && !isObject(newValue) && !Array.isArray(oldValue) && !Array.isArray(newValue)) {
|
|
115
121
|
if (!isEqual(oldValue, newValue)) {
|
|
@@ -322,7 +328,8 @@ function TreeDiffViewer({
|
|
|
322
328
|
newValue,
|
|
323
329
|
theme: themeName = "dark",
|
|
324
330
|
expandAll = false,
|
|
325
|
-
showUnchanged = true
|
|
331
|
+
showUnchanged = true,
|
|
332
|
+
scrollEnabled = true
|
|
326
333
|
}) {
|
|
327
334
|
const theme = themeName === "dark" ? darkTheme : lightTheme;
|
|
328
335
|
|
|
@@ -637,8 +644,12 @@ function TreeDiffViewer({
|
|
|
637
644
|
|
|
638
645
|
// Show header only if there are changes
|
|
639
646
|
const hasChanges = stats.added > 0 || stats.removed > 0 || stats.changed > 0;
|
|
647
|
+
|
|
648
|
+
// Inline mode must not claim `flex: 1`, or it would stretch to the pane and
|
|
649
|
+
// clip the rows an ancestor ScrollView is supposed to reveal.
|
|
650
|
+
const RowsContainer = scrollEnabled ? _reactNative.ScrollView : _reactNative.View;
|
|
640
651
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
641
|
-
style: [styles.container, {
|
|
652
|
+
style: [scrollEnabled ? styles.container : styles.containerInline, {
|
|
642
653
|
backgroundColor: theme.background
|
|
643
654
|
}],
|
|
644
655
|
children: [hasChanges && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
@@ -703,8 +714,8 @@ function TreeDiffViewer({
|
|
|
703
714
|
})]
|
|
704
715
|
})]
|
|
705
716
|
})
|
|
706
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(
|
|
707
|
-
style: styles.scrollView,
|
|
717
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(RowsContainer, {
|
|
718
|
+
style: scrollEnabled ? styles.scrollView : undefined,
|
|
708
719
|
showsVerticalScrollIndicator: false,
|
|
709
720
|
children: diffTree.length === 0 ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
710
721
|
style: styles.emptyState,
|
|
@@ -744,6 +755,10 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
744
755
|
borderRadius: 8,
|
|
745
756
|
overflow: "hidden"
|
|
746
757
|
},
|
|
758
|
+
containerInline: {
|
|
759
|
+
borderRadius: 8,
|
|
760
|
+
overflow: "hidden"
|
|
761
|
+
},
|
|
747
762
|
header: {
|
|
748
763
|
paddingHorizontal: 12,
|
|
749
764
|
paddingVertical: 8,
|
|
@@ -795,7 +810,7 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
795
810
|
justifyContent: "center",
|
|
796
811
|
flexDirection: "row",
|
|
797
812
|
borderBottomWidth: _reactNative.StyleSheet.hairlineWidth,
|
|
798
|
-
borderBottomColor: "rgba(
|
|
813
|
+
borderBottomColor: "rgba(128, 128, 128, 0.04)"
|
|
799
814
|
},
|
|
800
815
|
lineNumber: {
|
|
801
816
|
width: 32,
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.breadcrumb = breadcrumb;
|
|
7
|
+
exports.treeActionMap = treeActionMap;
|
|
8
|
+
exports.treeActionsFor = treeActionsFor;
|
|
9
|
+
exports.typeLabel = typeLabel;
|
|
10
|
+
var _jsonOps = require("./jsonOps.js");
|
|
11
|
+
/**
|
|
12
|
+
* What you can do to the node a data explorer has selected — as data, not UI.
|
|
13
|
+
*
|
|
14
|
+
* Two surfaces render this list and they look nothing alike: the dashboard's
|
|
15
|
+
* footer bar is a row of small chips beside a cursor, the phone's full-screen
|
|
16
|
+
* editor is a grid of thumb-sized tiles. Deriving both from one function is the
|
|
17
|
+
* point — "can this item move up" is a property of the DOCUMENT, and having two
|
|
18
|
+
* components each answer it from their own reading of `root` is how the two
|
|
19
|
+
* surfaces quietly start disagreeing about what's legal.
|
|
20
|
+
*
|
|
21
|
+
* So this module answers it once and hands back a list. The renderers decide
|
|
22
|
+
* what a disabled action looks like and which icon it wears; they never decide
|
|
23
|
+
* whether it applies.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/** The node a data explorer currently has selected. */
|
|
27
|
+
|
|
28
|
+
/** The node's type, as a badge shows it. */
|
|
29
|
+
function typeLabel(value) {
|
|
30
|
+
if (value === null) return "null";
|
|
31
|
+
if (Array.isArray(value)) return "array";
|
|
32
|
+
if ((0, _jsonOps.isRebuildableObject)(value)) return "object";
|
|
33
|
+
return typeof value;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** `a › b › 2` — reads as a location, which a bare index like `2` does not. */
|
|
37
|
+
function breadcrumb(path) {
|
|
38
|
+
return path.length === 0 ? "root" : path.join(" › ");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Index the list by id, for renderers that lay the six out in their own order.
|
|
43
|
+
*
|
|
44
|
+
* The bar and the dock genuinely disagree here — the bar puts the two move
|
|
45
|
+
* arrows together in the middle because they're icon-only and read as a pair,
|
|
46
|
+
* the dock follows the mockup's reading order. Neither ordering belongs in the
|
|
47
|
+
* capability list, so both look up what they need.
|
|
48
|
+
*/
|
|
49
|
+
function treeActionMap(actions) {
|
|
50
|
+
const map = {};
|
|
51
|
+
for (const action of actions) map[action.id] = action;
|
|
52
|
+
return map;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** A key that doesn't collide, for "add" on an object. */
|
|
56
|
+
function newKeyFor(container) {
|
|
57
|
+
if (!("newKey" in container)) return "newKey";
|
|
58
|
+
let n = 2;
|
|
59
|
+
while (`newKey ${n}` in container) n++;
|
|
60
|
+
return `newKey ${n}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The six things a selection can do, ALWAYS in this order and always all six.
|
|
65
|
+
*
|
|
66
|
+
* Returning the inapplicable ones as `enabled: false` rather than omitting them
|
|
67
|
+
* is deliberate and is why this returns a fixed-length list: a renderer that
|
|
68
|
+
* drops entries reflows every time the selection moves, so stepping from item 1
|
|
69
|
+
* to item 0 would slide the remaining controls sideways under a finger already
|
|
70
|
+
* on its way down. Stable position also means the same action is always in the
|
|
71
|
+
* same place, which is most of what makes a grid of six learnable.
|
|
72
|
+
*/
|
|
73
|
+
function treeActionsFor(root, selection, options = {}) {
|
|
74
|
+
const path = selection?.path ?? [];
|
|
75
|
+
const value = selection?.value;
|
|
76
|
+
const has = selection != null;
|
|
77
|
+
const isRoot = path.length === 0;
|
|
78
|
+
const parent = has && !isRoot ? (0, _jsonOps.getAtPath)(root, path.slice(0, -1)) : undefined;
|
|
79
|
+
const parentIsArray = Array.isArray(parent);
|
|
80
|
+
const index = parentIsArray ? Number(path[path.length - 1]) : -1;
|
|
81
|
+
const isArray = Array.isArray(value);
|
|
82
|
+
const isObject = (0, _jsonOps.isRebuildableObject)(value);
|
|
83
|
+
const isContainer = (0, _jsonOps.isEditableContainer)(value);
|
|
84
|
+
const canEditValue = has && (options.containersEditable === true || !isContainer);
|
|
85
|
+
|
|
86
|
+
// One "+" slot whose meaning follows the container type, rather than two
|
|
87
|
+
// mutually-exclusive buttons of which one is always dead.
|
|
88
|
+
const addedKey = isObject ? newKeyFor(value) : "";
|
|
89
|
+
const add = isObject ? {
|
|
90
|
+
id: "add",
|
|
91
|
+
label: "Add key",
|
|
92
|
+
enabled: true,
|
|
93
|
+
op: {
|
|
94
|
+
kind: "addKey",
|
|
95
|
+
path,
|
|
96
|
+
key: addedKey,
|
|
97
|
+
value: (0, _jsonOps.suggestedNewValue)(value)
|
|
98
|
+
},
|
|
99
|
+
selectAfter: [...path, addedKey]
|
|
100
|
+
} : {
|
|
101
|
+
id: "add",
|
|
102
|
+
label: "Append",
|
|
103
|
+
enabled: isArray,
|
|
104
|
+
op: isArray ? {
|
|
105
|
+
kind: "append",
|
|
106
|
+
path,
|
|
107
|
+
value: (0, _jsonOps.suggestedNewValue)(value)
|
|
108
|
+
} : null,
|
|
109
|
+
selectAfter: isArray ? [...path, String(value.length)] : undefined
|
|
110
|
+
};
|
|
111
|
+
return [
|
|
112
|
+
// A boolean has exactly two states, so there is nothing to ask and nothing
|
|
113
|
+
// to type — an editor for it would be a screen whose only job is to offer
|
|
114
|
+
// the value you didn't pick. It flips in place instead.
|
|
115
|
+
typeof value === "boolean" ? {
|
|
116
|
+
id: "editValue",
|
|
117
|
+
label: "Toggle",
|
|
118
|
+
enabled: true,
|
|
119
|
+
op: {
|
|
120
|
+
kind: "replace",
|
|
121
|
+
path,
|
|
122
|
+
value: !value
|
|
123
|
+
}
|
|
124
|
+
} : {
|
|
125
|
+
id: "editValue",
|
|
126
|
+
label: "Edit value",
|
|
127
|
+
enabled: canEditValue,
|
|
128
|
+
op: null
|
|
129
|
+
}, add, {
|
|
130
|
+
// `duplicate` handles object keys too (it mints a "<key> copy" in place),
|
|
131
|
+
// so this applies to any entry that has a parent.
|
|
132
|
+
id: "duplicate",
|
|
133
|
+
label: "Duplicate",
|
|
134
|
+
enabled: has && !isRoot,
|
|
135
|
+
op: has && !isRoot ? {
|
|
136
|
+
kind: "duplicate",
|
|
137
|
+
path
|
|
138
|
+
} : null
|
|
139
|
+
}, {
|
|
140
|
+
id: "moveUp",
|
|
141
|
+
label: "Move up",
|
|
142
|
+
enabled: has && parentIsArray && index > 0,
|
|
143
|
+
op: has && parentIsArray && index > 0 ? {
|
|
144
|
+
kind: "move",
|
|
145
|
+
path,
|
|
146
|
+
toIndex: index - 1
|
|
147
|
+
} : null
|
|
148
|
+
}, {
|
|
149
|
+
id: "moveDown",
|
|
150
|
+
label: "Move down",
|
|
151
|
+
enabled: has && parentIsArray && index > -1 && index < parent.length - 1,
|
|
152
|
+
op: has && parentIsArray && index > -1 && index < parent.length - 1 ? {
|
|
153
|
+
kind: "move",
|
|
154
|
+
path,
|
|
155
|
+
toIndex: index + 1
|
|
156
|
+
} : null
|
|
157
|
+
}, {
|
|
158
|
+
id: "remove",
|
|
159
|
+
label: "Remove",
|
|
160
|
+
danger: true,
|
|
161
|
+
enabled: has && !isRoot,
|
|
162
|
+
op: has && !isRoot ? {
|
|
163
|
+
kind: "remove",
|
|
164
|
+
path
|
|
165
|
+
} : null
|
|
166
|
+
}];
|
|
167
|
+
}
|
|
@@ -180,10 +180,10 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
180
180
|
width: "100%"
|
|
181
181
|
},
|
|
182
182
|
optionContainerSelected: {
|
|
183
|
-
backgroundColor: "rgba(
|
|
183
|
+
backgroundColor: "rgba(128, 128, 128, 0.1)"
|
|
184
184
|
},
|
|
185
185
|
optionContainerPressed: {
|
|
186
|
-
backgroundColor: "rgba(
|
|
186
|
+
backgroundColor: "rgba(128, 128, 128, 0.2)"
|
|
187
187
|
},
|
|
188
188
|
optionLeft: {
|
|
189
189
|
flexDirection: "row",
|
|
@@ -274,10 +274,10 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
274
274
|
height: OPTION_HEIGHT
|
|
275
275
|
},
|
|
276
276
|
optionContainerSelected: {
|
|
277
|
-
backgroundColor: "rgba(
|
|
277
|
+
backgroundColor: "rgba(128, 128, 128, 0.1)"
|
|
278
278
|
},
|
|
279
279
|
optionContainerPressed: {
|
|
280
|
-
backgroundColor: "rgba(
|
|
280
|
+
backgroundColor: "rgba(128, 128, 128, 0.2)"
|
|
281
281
|
},
|
|
282
282
|
optionLeft: {
|
|
283
283
|
flexDirection: "row",
|