@buoy-gg/shared-ui 7.0.32 → 7.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/JsModal.js +70 -28
- package/lib/commonjs/hooks/index.js +26 -0
- package/lib/commonjs/hooks/safe-area-impl.js +1 -1
- package/lib/commonjs/hooks/useChangeLog.js +55 -0
- package/lib/commonjs/hooks/useEventStoreEvents.js +65 -0
- package/lib/commonjs/hooks/usePersistedState.js +45 -10
- package/lib/commonjs/index.js +143 -0
- package/lib/commonjs/storage/definePersistedSetting.js +67 -0
- package/lib/commonjs/storage/devToolsStorageKeys.js +12 -0
- package/lib/commonjs/storage/index.js +8 -1
- package/lib/commonjs/stores/ChangeLog.js +197 -0
- package/lib/commonjs/stores/createToolStore.js +175 -0
- package/lib/commonjs/stores/index.js +15 -1
- package/lib/commonjs/sync/toolSyncAdapter.js +63 -0
- package/lib/commonjs/sync/wireForm.js +172 -0
- package/lib/commonjs/tools/defineTool.js +79 -0
- package/lib/commonjs/ui/components/ChangeRow.js +110 -0
- package/lib/commonjs/ui/components/ChipStrip.js +94 -0
- package/lib/commonjs/ui/components/DetailViewToggle.js +130 -0
- package/lib/commonjs/ui/components/DevToolsCard.js +3 -1
- package/lib/commonjs/ui/components/EmptyState.js +10 -2
- package/lib/commonjs/ui/components/EntityFilterView.js +354 -0
- package/lib/commonjs/ui/components/ExportPreview.js +174 -0
- package/lib/commonjs/ui/components/InfoRow.js +90 -0
- package/lib/commonjs/ui/components/ModalHeader.js +40 -7
- package/lib/commonjs/ui/components/Pill.js +114 -0
- package/lib/commonjs/ui/components/ToggleRow.js +116 -0
- package/lib/commonjs/ui/components/ToolEmptyState.js +154 -0
- package/lib/commonjs/ui/components/ToolFooter.js +204 -0
- package/lib/commonjs/ui/components/WindowControls.js +8 -5
- package/lib/commonjs/ui/components/index.js +113 -1
- package/lib/commonjs/ui/index.js +36 -2
- package/lib/commonjs/ui/listPresets.js +43 -0
- package/lib/commonjs/ui/night/primitives.js +3 -1
- package/lib/commonjs/ui/otto/OttoSprite.js +510 -0
- package/lib/commonjs/ui/otto/index.js +38 -0
- package/lib/commonjs/ui/otto/ottoEngine.js +2734 -0
- package/lib/commonjs/ui/otto/ottoSheet.js +191 -0
- package/lib/commonjs/utils/snapshotProviderKit.js +167 -0
- package/lib/commonjs/utils/stateTools.js +160 -0
- package/lib/module/JsModal.js +70 -28
- package/lib/module/hooks/index.js +3 -1
- package/lib/module/hooks/safe-area-impl.js +1 -1
- package/lib/module/hooks/useChangeLog.js +50 -0
- package/lib/module/hooks/useEventStoreEvents.js +61 -0
- package/lib/module/hooks/usePersistedState.js +44 -10
- package/lib/module/index.js +11 -1
- package/lib/module/storage/definePersistedSetting.js +63 -0
- package/lib/module/storage/devToolsStorageKeys.js +12 -0
- package/lib/module/storage/index.js +2 -1
- package/lib/module/stores/ChangeLog.js +192 -0
- package/lib/module/stores/createToolStore.js +171 -0
- package/lib/module/stores/index.js +3 -1
- package/lib/module/sync/toolSyncAdapter.js +58 -0
- package/lib/module/sync/wireForm.js +159 -0
- package/lib/module/tools/defineTool.js +74 -0
- package/lib/module/ui/components/ChangeRow.js +105 -0
- package/lib/module/ui/components/ChipStrip.js +91 -0
- package/lib/module/ui/components/DetailViewToggle.js +125 -0
- package/lib/module/ui/components/DevToolsCard.js +3 -1
- package/lib/module/ui/components/EmptyState.js +10 -2
- package/lib/module/ui/components/EntityFilterView.js +350 -0
- package/lib/module/ui/components/ExportPreview.js +169 -0
- package/lib/module/ui/components/InfoRow.js +86 -0
- package/lib/module/ui/components/ModalHeader.js +40 -7
- package/lib/module/ui/components/Pill.js +110 -0
- package/lib/module/ui/components/ToggleRow.js +112 -0
- package/lib/module/ui/components/ToolEmptyState.js +149 -0
- package/lib/module/ui/components/ToolFooter.js +196 -0
- package/lib/module/ui/components/WindowControls.js +8 -5
- package/lib/module/ui/components/index.js +13 -1
- package/lib/module/ui/index.js +7 -1
- package/lib/module/ui/listPresets.js +39 -0
- package/lib/module/ui/night/primitives.js +3 -1
- package/lib/module/ui/otto/OttoSprite.js +496 -0
- package/lib/module/ui/otto/index.js +20 -0
- package/lib/module/ui/otto/ottoEngine.js +2726 -0
- package/lib/module/ui/otto/ottoSheet.js +180 -0
- package/lib/module/utils/snapshotProviderKit.js +156 -0
- package/lib/module/utils/stateTools.js +154 -0
- package/lib/typescript/commonjs/JsModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/hooks/index.d.ts +3 -1
- package/lib/typescript/commonjs/hooks/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/commonjs/hooks/useChangeLog.d.ts +38 -0
- package/lib/typescript/commonjs/hooks/useChangeLog.d.ts.map +1 -0
- package/lib/typescript/commonjs/hooks/useEventStoreEvents.d.ts +25 -0
- package/lib/typescript/commonjs/hooks/useEventStoreEvents.d.ts.map +1 -0
- package/lib/typescript/commonjs/hooks/usePersistedState.d.ts +34 -5
- package/lib/typescript/commonjs/hooks/usePersistedState.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +6 -1
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/storage/definePersistedSetting.d.ts +39 -0
- package/lib/typescript/commonjs/storage/definePersistedSetting.d.ts.map +1 -0
- package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts +12 -0
- package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts.map +1 -1
- package/lib/typescript/commonjs/storage/index.d.ts +1 -0
- package/lib/typescript/commonjs/storage/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/stores/ChangeLog.d.ts +100 -0
- package/lib/typescript/commonjs/stores/ChangeLog.d.ts.map +1 -0
- package/lib/typescript/commonjs/stores/createToolStore.d.ts +92 -0
- package/lib/typescript/commonjs/stores/createToolStore.d.ts.map +1 -0
- package/lib/typescript/commonjs/stores/index.d.ts +2 -0
- package/lib/typescript/commonjs/stores/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/sync/toolSyncAdapter.d.ts +66 -0
- package/lib/typescript/commonjs/sync/toolSyncAdapter.d.ts.map +1 -0
- package/lib/typescript/commonjs/sync/wireForm.d.ts +100 -0
- package/lib/typescript/commonjs/sync/wireForm.d.ts.map +1 -0
- package/lib/typescript/commonjs/tools/defineTool.d.ts +100 -0
- package/lib/typescript/commonjs/tools/defineTool.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ChangeRow.d.ts +52 -0
- package/lib/typescript/commonjs/ui/components/ChangeRow.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ChipStrip.d.ts +41 -0
- package/lib/typescript/commonjs/ui/components/ChipStrip.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/DetailViewToggle.d.ts +36 -0
- package/lib/typescript/commonjs/ui/components/DetailViewToggle.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/DevToolsCard.d.ts +8 -1
- package/lib/typescript/commonjs/ui/components/DevToolsCard.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/EmptyState.d.ts +14 -1
- package/lib/typescript/commonjs/ui/components/EmptyState.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/EntityFilterView.d.ts +51 -0
- package/lib/typescript/commonjs/ui/components/EntityFilterView.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ExportPreview.d.ts +48 -0
- package/lib/typescript/commonjs/ui/components/ExportPreview.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/InfoRow.d.ts +33 -0
- package/lib/typescript/commonjs/ui/components/InfoRow.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ModalHeader.d.ts +31 -1
- package/lib/typescript/commonjs/ui/components/ModalHeader.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/Pill.d.ts +38 -0
- package/lib/typescript/commonjs/ui/components/Pill.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ToggleRow.d.ts +33 -0
- package/lib/typescript/commonjs/ui/components/ToggleRow.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ToolEmptyState.d.ts +113 -0
- package/lib/typescript/commonjs/ui/components/ToolEmptyState.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ToolFooter.d.ts +69 -0
- package/lib/typescript/commonjs/ui/components/ToolFooter.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/WindowControls.d.ts +7 -1
- package/lib/typescript/commonjs/ui/components/WindowControls.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/index.d.ts +11 -0
- package/lib/typescript/commonjs/ui/components/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/index.d.ts +2 -0
- package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/listPresets.d.ts +28 -0
- package/lib/typescript/commonjs/ui/listPresets.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/night/primitives.d.ts +3 -1
- package/lib/typescript/commonjs/ui/night/primitives.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/otto/OttoSprite.d.ts +103 -0
- package/lib/typescript/commonjs/ui/otto/OttoSprite.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/otto/index.d.ts +19 -0
- package/lib/typescript/commonjs/ui/otto/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/otto/ottoEngine.d.ts +2205 -0
- package/lib/typescript/commonjs/ui/otto/ottoEngine.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/otto/ottoSheet.d.ts +73 -0
- package/lib/typescript/commonjs/ui/otto/ottoSheet.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/snapshotProviderKit.d.ts +81 -0
- package/lib/typescript/commonjs/utils/snapshotProviderKit.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/stateTools.d.ts +44 -0
- package/lib/typescript/commonjs/utils/stateTools.d.ts.map +1 -0
- package/lib/typescript/module/JsModal.d.ts.map +1 -1
- package/lib/typescript/module/hooks/index.d.ts +3 -1
- package/lib/typescript/module/hooks/index.d.ts.map +1 -1
- package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/module/hooks/useChangeLog.d.ts +38 -0
- package/lib/typescript/module/hooks/useChangeLog.d.ts.map +1 -0
- package/lib/typescript/module/hooks/useEventStoreEvents.d.ts +25 -0
- package/lib/typescript/module/hooks/useEventStoreEvents.d.ts.map +1 -0
- package/lib/typescript/module/hooks/usePersistedState.d.ts +34 -5
- package/lib/typescript/module/hooks/usePersistedState.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +6 -1
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/storage/definePersistedSetting.d.ts +39 -0
- package/lib/typescript/module/storage/definePersistedSetting.d.ts.map +1 -0
- package/lib/typescript/module/storage/devToolsStorageKeys.d.ts +12 -0
- package/lib/typescript/module/storage/devToolsStorageKeys.d.ts.map +1 -1
- package/lib/typescript/module/storage/index.d.ts +1 -0
- package/lib/typescript/module/storage/index.d.ts.map +1 -1
- package/lib/typescript/module/stores/ChangeLog.d.ts +100 -0
- package/lib/typescript/module/stores/ChangeLog.d.ts.map +1 -0
- package/lib/typescript/module/stores/createToolStore.d.ts +92 -0
- package/lib/typescript/module/stores/createToolStore.d.ts.map +1 -0
- package/lib/typescript/module/stores/index.d.ts +2 -0
- package/lib/typescript/module/stores/index.d.ts.map +1 -1
- package/lib/typescript/module/sync/toolSyncAdapter.d.ts +66 -0
- package/lib/typescript/module/sync/toolSyncAdapter.d.ts.map +1 -0
- package/lib/typescript/module/sync/wireForm.d.ts +100 -0
- package/lib/typescript/module/sync/wireForm.d.ts.map +1 -0
- package/lib/typescript/module/tools/defineTool.d.ts +100 -0
- package/lib/typescript/module/tools/defineTool.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ChangeRow.d.ts +52 -0
- package/lib/typescript/module/ui/components/ChangeRow.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ChipStrip.d.ts +41 -0
- package/lib/typescript/module/ui/components/ChipStrip.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/DetailViewToggle.d.ts +36 -0
- package/lib/typescript/module/ui/components/DetailViewToggle.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/DevToolsCard.d.ts +8 -1
- package/lib/typescript/module/ui/components/DevToolsCard.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/EmptyState.d.ts +14 -1
- package/lib/typescript/module/ui/components/EmptyState.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/EntityFilterView.d.ts +51 -0
- package/lib/typescript/module/ui/components/EntityFilterView.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ExportPreview.d.ts +48 -0
- package/lib/typescript/module/ui/components/ExportPreview.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/InfoRow.d.ts +33 -0
- package/lib/typescript/module/ui/components/InfoRow.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ModalHeader.d.ts +31 -1
- package/lib/typescript/module/ui/components/ModalHeader.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/Pill.d.ts +38 -0
- package/lib/typescript/module/ui/components/Pill.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ToggleRow.d.ts +33 -0
- package/lib/typescript/module/ui/components/ToggleRow.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ToolEmptyState.d.ts +113 -0
- package/lib/typescript/module/ui/components/ToolEmptyState.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ToolFooter.d.ts +69 -0
- package/lib/typescript/module/ui/components/ToolFooter.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/WindowControls.d.ts +7 -1
- package/lib/typescript/module/ui/components/WindowControls.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/index.d.ts +11 -0
- package/lib/typescript/module/ui/components/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/index.d.ts +2 -0
- package/lib/typescript/module/ui/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/listPresets.d.ts +28 -0
- package/lib/typescript/module/ui/listPresets.d.ts.map +1 -0
- package/lib/typescript/module/ui/night/primitives.d.ts +3 -1
- package/lib/typescript/module/ui/night/primitives.d.ts.map +1 -1
- package/lib/typescript/module/ui/otto/OttoSprite.d.ts +103 -0
- package/lib/typescript/module/ui/otto/OttoSprite.d.ts.map +1 -0
- package/lib/typescript/module/ui/otto/index.d.ts +19 -0
- package/lib/typescript/module/ui/otto/index.d.ts.map +1 -0
- package/lib/typescript/module/ui/otto/ottoEngine.d.ts +2205 -0
- package/lib/typescript/module/ui/otto/ottoEngine.d.ts.map +1 -0
- package/lib/typescript/module/ui/otto/ottoSheet.d.ts +73 -0
- package/lib/typescript/module/ui/otto/ottoSheet.d.ts.map +1 -0
- package/lib/typescript/module/utils/snapshotProviderKit.d.ts +81 -0
- package/lib/typescript/module/utils/snapshotProviderKit.d.ts.map +1 -0
- package/lib/typescript/module/utils/stateTools.d.ts +44 -0
- package/lib/typescript/module/utils/stateTools.d.ts.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Otto's precomputed animation.
|
|
5
|
+
*
|
|
6
|
+
* Every state is a short loop (48 ticks at most). This module renders that
|
|
7
|
+
* loop once, splits it into a BODY layer and a 7-frame WATER layer (they
|
|
8
|
+
* composite back pixel-for-pixel: compose() only paints water into empty
|
|
9
|
+
* cells and blanks a submerged body below the waterline), dedupes the
|
|
10
|
+
* frames, and turns each distinct frame into merged rectangles. The shipping
|
|
11
|
+
* <Otto/> mounts those rectangles ONCE as a strip of static Views and slides
|
|
12
|
+
* a window over the strip on the UI thread.
|
|
13
|
+
*
|
|
14
|
+
* Why: the buoy-optimize rounds in OTTO_PERF_PLAN.md showed that any renderer
|
|
15
|
+
* re-creating Views per tick pegs the JS thread (5 FPS at 34 sprites, dropped
|
|
16
|
+
* UI frames even at 1 sprite), while "mount once, move a window natively"
|
|
17
|
+
* costs nothing per tick and keeps moving while JS is blocked.
|
|
18
|
+
*
|
|
19
|
+
* Everything here is pure `react-native`-free TypeScript, cached per state.
|
|
20
|
+
*/
|
|
21
|
+
import { OTTO_GRID, OTTO_PALETTE, ottoWaterRows, renderOttoFrame } from "./ottoEngine.js";
|
|
22
|
+
export const CELLS = OTTO_GRID * OTTO_GRID;
|
|
23
|
+
export const WATER_ROW0 = 13;
|
|
24
|
+
export const WATER_ROWS = OTTO_GRID - WATER_ROW0;
|
|
25
|
+
export const WATER_CELLS = WATER_ROWS * OTTO_GRID;
|
|
26
|
+
/** The wave is a function of floor(t/2) mod 7. */
|
|
27
|
+
export const WATER_FRAMES = 7;
|
|
28
|
+
export const TRANSPARENT = "transparent";
|
|
29
|
+
/** Longest state cycle in ticks (idle and sleep are 48). */
|
|
30
|
+
export const MAX_PERIOD = 48;
|
|
31
|
+
export function gridKey(grid) {
|
|
32
|
+
return grid.map(r => r.join("")).join("|");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Flat 256 colours, row-major, `transparent` for empty cells. */
|
|
36
|
+
export function flatColors(grid) {
|
|
37
|
+
const out = new Array(CELLS);
|
|
38
|
+
for (let y = 0; y < OTTO_GRID; y++) {
|
|
39
|
+
const row = grid[y];
|
|
40
|
+
for (let x = 0; x < OTTO_GRID; x++) out[y * OTTO_GRID + x] = OTTO_PALETTE[row[x]] ?? TRANSPARENT;
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ---------------------------------------------------------------- cycle ---
|
|
46
|
+
|
|
47
|
+
const cycleCache = new Map();
|
|
48
|
+
export function ottoCycle(state, keyline) {
|
|
49
|
+
const cacheKey = `${state}|${keyline ? 1 : 0}`;
|
|
50
|
+
const hit = cycleCache.get(cacheKey);
|
|
51
|
+
if (hit) return hit;
|
|
52
|
+
const keys = [];
|
|
53
|
+
const grids = [];
|
|
54
|
+
for (let t = 0; t < MAX_PERIOD * 2; t++) {
|
|
55
|
+
const g = renderOttoFrame(state, t, {
|
|
56
|
+
water: false,
|
|
57
|
+
keyline
|
|
58
|
+
});
|
|
59
|
+
grids.push(g);
|
|
60
|
+
keys.push(gridKey(g));
|
|
61
|
+
}
|
|
62
|
+
let period = MAX_PERIOD;
|
|
63
|
+
for (let P = 1; P <= MAX_PERIOD; P++) {
|
|
64
|
+
let ok = true;
|
|
65
|
+
for (let t = 0; t < MAX_PERIOD; t++) {
|
|
66
|
+
if (keys[t] !== keys[t + P]) {
|
|
67
|
+
ok = false;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (ok) {
|
|
72
|
+
period = P;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const body = grids.slice(0, period).map(flatColors);
|
|
77
|
+
const water = [];
|
|
78
|
+
for (let w = 0; w < WATER_FRAMES; w++) {
|
|
79
|
+
const flat = [];
|
|
80
|
+
for (const row of ottoWaterRows(w * 2)) for (const k of row) flat.push(OTTO_PALETTE[k] ?? TRANSPARENT);
|
|
81
|
+
water.push(flat);
|
|
82
|
+
}
|
|
83
|
+
const cycle = {
|
|
84
|
+
period,
|
|
85
|
+
body,
|
|
86
|
+
water
|
|
87
|
+
};
|
|
88
|
+
cycleCache.set(cacheKey, cycle);
|
|
89
|
+
return cycle;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Frame indexes for a cycle at local tick `t`. */
|
|
93
|
+
export function cycleIndexes(t, period) {
|
|
94
|
+
const local = Math.max(0, t);
|
|
95
|
+
return {
|
|
96
|
+
bi: local % period,
|
|
97
|
+
wi: Math.floor(local / 2) % WATER_FRAMES
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ---------------------------------------------------------------- rects ---
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Same-colour runs per row, then runs merged with the identical run directly
|
|
105
|
+
* below them — roughly a third fewer Views than row runs alone. Covers
|
|
106
|
+
* exactly the non-transparent cells, never overlaps (proved offline over
|
|
107
|
+
* every frame of every state).
|
|
108
|
+
*/
|
|
109
|
+
export function rectsOf(colors, cols, rows) {
|
|
110
|
+
const open = [];
|
|
111
|
+
const done = [];
|
|
112
|
+
for (let y = 0; y < rows; y++) {
|
|
113
|
+
const rowRuns = [];
|
|
114
|
+
let x = 0;
|
|
115
|
+
while (x < cols) {
|
|
116
|
+
const color = colors[y * cols + x];
|
|
117
|
+
let w = 1;
|
|
118
|
+
while (x + w < cols && colors[y * cols + x + w] === color) w++;
|
|
119
|
+
if (color !== TRANSPARENT) rowRuns.push({
|
|
120
|
+
x,
|
|
121
|
+
y,
|
|
122
|
+
w,
|
|
123
|
+
h: 1,
|
|
124
|
+
color
|
|
125
|
+
});
|
|
126
|
+
x += w;
|
|
127
|
+
}
|
|
128
|
+
const next = [];
|
|
129
|
+
for (const r of rowRuns) {
|
|
130
|
+
const above = open.find(o => o.x === r.x && o.w === r.w && o.color === r.color && o.y + o.h === r.y);
|
|
131
|
+
if (above) {
|
|
132
|
+
above.h += 1;
|
|
133
|
+
next.push(above);
|
|
134
|
+
} else {
|
|
135
|
+
next.push(r);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
for (const o of open) if (!next.includes(o)) done.push(o);
|
|
139
|
+
open.length = 0;
|
|
140
|
+
open.push(...next);
|
|
141
|
+
}
|
|
142
|
+
done.push(...open);
|
|
143
|
+
return done;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ---------------------------------------------------------------- sheets --
|
|
147
|
+
|
|
148
|
+
/** One layer as a strip of distinct frames, and which frame each tick shows. */
|
|
149
|
+
|
|
150
|
+
const sheetCache = new Map();
|
|
151
|
+
function stripOf(frames, cols, rows) {
|
|
152
|
+
const keys = frames.map(f => f.join(","));
|
|
153
|
+
const indexOf = new Map();
|
|
154
|
+
const distinct = [];
|
|
155
|
+
keys.forEach((k, i) => {
|
|
156
|
+
if (!indexOf.has(k)) {
|
|
157
|
+
indexOf.set(k, distinct.length);
|
|
158
|
+
distinct.push(rectsOf(frames[i], cols, rows));
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
return {
|
|
162
|
+
colOf: keys.map(k => indexOf.get(k) ?? 0),
|
|
163
|
+
frames: distinct
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** Both layers of a state as strips of rectangles. Pure; cached per state. */
|
|
168
|
+
export function ottoSheets(state, keyline) {
|
|
169
|
+
const key = `${state}|${keyline ? 1 : 0}`;
|
|
170
|
+
const hit = sheetCache.get(key);
|
|
171
|
+
if (hit) return hit;
|
|
172
|
+
const cycle = ottoCycle(state, keyline);
|
|
173
|
+
const built = {
|
|
174
|
+
period: cycle.period,
|
|
175
|
+
body: stripOf(cycle.body, OTTO_GRID, OTTO_GRID),
|
|
176
|
+
water: stripOf(cycle.water, OTTO_GRID, WATER_ROWS)
|
|
177
|
+
};
|
|
178
|
+
sheetCache.set(key, built);
|
|
179
|
+
return built;
|
|
180
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* snapshotProviderKit — the parts of a Time Machine `StateSnapshotProvider`
|
|
5
|
+
* that are the same for every source.
|
|
6
|
+
*
|
|
7
|
+
* storage, redux, zustand, jotai and react-query each register a provider
|
|
8
|
+
* (see stateSnapshotRegistry.ts). What differs is how they read and write
|
|
9
|
+
* their source. What was copied five times is:
|
|
10
|
+
*
|
|
11
|
+
* - the restore SCOPE gate: `excludeKeys` (touch all but these) and
|
|
12
|
+
* `includeKeys` (touch only these), the "N item(s) excluded by you"
|
|
13
|
+
* warning, and the empty `StateSnapshotRestoreResult`;
|
|
14
|
+
* - the preview VERDICT ladder: removed → added → unchanged → too-large →
|
|
15
|
+
* changed, with the 256 KB per-item render cap;
|
|
16
|
+
* - the "won't apply" override: a difference restore cannot apply must say
|
|
17
|
+
* so instead of rendering as a green change.
|
|
18
|
+
*
|
|
19
|
+
* The parts that stay per-tool are the ones that matter: redux verifies the
|
|
20
|
+
* jump by reference identity, zustand grafts action functions back, jotai
|
|
21
|
+
* leaves derived atoms to recompute, storage gates MMKV buffers and
|
|
22
|
+
* biometric keys, react-query diffs a comparable projection.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { boundedDeepEqual, jsonLikelyLargerThan } from "../dataViewer/objectDiff.js";
|
|
26
|
+
/** Beyond this a preview item is "too-large": restore still applies it, the diff isn't drawn. */
|
|
27
|
+
export const PREVIEW_ITEM_RENDER_BYTE_LIMIT = 256 * 1024;
|
|
28
|
+
/**
|
|
29
|
+
* Both option lists use preview item keys, and both mean "leave everything
|
|
30
|
+
* else untouched in BOTH directions". `includeKeys` wins when present;
|
|
31
|
+
* `excludeKeys` still applies on top.
|
|
32
|
+
*/
|
|
33
|
+
export function createRestoreScope(options) {
|
|
34
|
+
const excludedSet = new Set(options?.excludeKeys ?? []);
|
|
35
|
+
const includedSet = options?.includeKeys ? new Set(options.includeKeys) : null;
|
|
36
|
+
let excludedHits = 0;
|
|
37
|
+
const touch = key => !excludedSet.has(key) && (!includedSet || includedSet.has(key));
|
|
38
|
+
return {
|
|
39
|
+
touch,
|
|
40
|
+
allows(key) {
|
|
41
|
+
if (touch(key)) return true;
|
|
42
|
+
excludedHits += 1;
|
|
43
|
+
return false;
|
|
44
|
+
},
|
|
45
|
+
countExcluded(n) {
|
|
46
|
+
excludedHits += n;
|
|
47
|
+
},
|
|
48
|
+
get excludedHits() {
|
|
49
|
+
return excludedHits;
|
|
50
|
+
},
|
|
51
|
+
excludedWarning(noun) {
|
|
52
|
+
return excludedHits > 0 ? `${excludedHits} ${noun} excluded by you` : null;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** A fresh, successful, empty result to accumulate into. */
|
|
58
|
+
export function emptyRestoreResult() {
|
|
59
|
+
return {
|
|
60
|
+
ok: true,
|
|
61
|
+
applied: 0,
|
|
62
|
+
skipped: [],
|
|
63
|
+
warnings: []
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** A failed result with one warning (an empty or unusable snapshot). */
|
|
68
|
+
export function failedRestore(warning) {
|
|
69
|
+
return {
|
|
70
|
+
ok: false,
|
|
71
|
+
applied: 0,
|
|
72
|
+
skipped: [],
|
|
73
|
+
warnings: [warning]
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** A failed result with one skipped item and its reason. */
|
|
78
|
+
export function skippedRestore(id, reason) {
|
|
79
|
+
return {
|
|
80
|
+
ok: false,
|
|
81
|
+
applied: 0,
|
|
82
|
+
skipped: [{
|
|
83
|
+
id,
|
|
84
|
+
reason
|
|
85
|
+
}],
|
|
86
|
+
warnings: []
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The verdict ladder: removed → added → unchanged → too-large → changed.
|
|
91
|
+
* Callers layer source-specific verdicts (`wont-apply`, `recomputes`) on top
|
|
92
|
+
* with `wontApply()`.
|
|
93
|
+
*/
|
|
94
|
+
export function classifyPreviewItem(input, options = {}) {
|
|
95
|
+
const {
|
|
96
|
+
key,
|
|
97
|
+
label,
|
|
98
|
+
oldValue,
|
|
99
|
+
newValue,
|
|
100
|
+
inOld,
|
|
101
|
+
inNew
|
|
102
|
+
} = input;
|
|
103
|
+
if (!inNew) return {
|
|
104
|
+
key,
|
|
105
|
+
label,
|
|
106
|
+
verdict: "removed",
|
|
107
|
+
oldValue
|
|
108
|
+
};
|
|
109
|
+
if (!inOld) return {
|
|
110
|
+
key,
|
|
111
|
+
label,
|
|
112
|
+
verdict: "added",
|
|
113
|
+
newValue
|
|
114
|
+
};
|
|
115
|
+
const equal = options.equal ?? boundedDeepEqual;
|
|
116
|
+
if (equal(oldValue, newValue)) return {
|
|
117
|
+
key,
|
|
118
|
+
label,
|
|
119
|
+
verdict: "unchanged"
|
|
120
|
+
};
|
|
121
|
+
const tooLarge = options.tooLarge ?? (value => jsonLikelyLargerThan(value, PREVIEW_ITEM_RENDER_BYTE_LIMIT));
|
|
122
|
+
if (tooLarge(oldValue) || tooLarge(newValue)) {
|
|
123
|
+
return {
|
|
124
|
+
key,
|
|
125
|
+
label,
|
|
126
|
+
verdict: "too-large",
|
|
127
|
+
reason: options.tooLargeReason ?? "value too large to render a diff — restore still applies it"
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
key,
|
|
132
|
+
label,
|
|
133
|
+
verdict: "changed",
|
|
134
|
+
oldValue,
|
|
135
|
+
newValue
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Mark an item as something restore cannot apply. An unchanged item is left
|
|
141
|
+
* alone — there is nothing to apply, so nothing is being refused.
|
|
142
|
+
*/
|
|
143
|
+
export function wontApply(item, reason) {
|
|
144
|
+
if (item.verdict === "unchanged") return item;
|
|
145
|
+
return {
|
|
146
|
+
...item,
|
|
147
|
+
verdict: "wont-apply",
|
|
148
|
+
reason
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Every key present in either record, once. */
|
|
153
|
+
export function unionKeys(a, b) {
|
|
154
|
+
const keysOf = r => r === undefined ? [] : r instanceof Map ? Array.from(r.keys()) : Object.keys(r);
|
|
155
|
+
return new Set([...keysOf(a), ...keysOf(b)]);
|
|
156
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* stateTools — helpers the state tools (redux / zustand / jotai) each carried
|
|
5
|
+
* a private copy of. Pure functions; no React, no RN.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ============================================
|
|
9
|
+
// Entity color
|
|
10
|
+
// ============================================
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Consistent color for a named entity (a zustand store, a jotai atom, a redux
|
|
14
|
+
* slice). Exact match on `known` wins, then a substring match, then a stable
|
|
15
|
+
* HSL hash of the name rendered as `#rrggbb` so the "color + alpha hex"
|
|
16
|
+
* pattern works everywhere.
|
|
17
|
+
*/
|
|
18
|
+
export function entityColor(name, known = {}) {
|
|
19
|
+
const lower = name.toLowerCase();
|
|
20
|
+
if (known[lower]) return known[lower];
|
|
21
|
+
for (const [key, color] of Object.entries(known)) {
|
|
22
|
+
if (lower.includes(key)) return color;
|
|
23
|
+
}
|
|
24
|
+
const hash = name.split("").reduce((acc, char) => acc + char.charCodeAt(0), 0);
|
|
25
|
+
const hue = hash * 137 % 360;
|
|
26
|
+
const s = 0.7;
|
|
27
|
+
const l = 0.6;
|
|
28
|
+
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
29
|
+
const x = c * (1 - Math.abs(hue / 60 % 2 - 1));
|
|
30
|
+
const m = l - c / 2;
|
|
31
|
+
let r = 0;
|
|
32
|
+
let g = 0;
|
|
33
|
+
let b = 0;
|
|
34
|
+
if (hue < 60) {
|
|
35
|
+
r = c;
|
|
36
|
+
g = x;
|
|
37
|
+
} else if (hue < 120) {
|
|
38
|
+
r = x;
|
|
39
|
+
g = c;
|
|
40
|
+
} else if (hue < 180) {
|
|
41
|
+
g = c;
|
|
42
|
+
b = x;
|
|
43
|
+
} else if (hue < 240) {
|
|
44
|
+
g = x;
|
|
45
|
+
b = c;
|
|
46
|
+
} else if (hue < 300) {
|
|
47
|
+
r = x;
|
|
48
|
+
b = c;
|
|
49
|
+
} else {
|
|
50
|
+
r = c;
|
|
51
|
+
b = x;
|
|
52
|
+
}
|
|
53
|
+
const toHex = v => Math.round((v + m) * 255).toString(16).padStart(2, "0");
|
|
54
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ============================================
|
|
58
|
+
// Value preview
|
|
59
|
+
// ============================================
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* One-line preview of an arbitrary value for a list row: strings quoted and
|
|
63
|
+
* truncated, arrays and objects stringified when short, otherwise collapsed
|
|
64
|
+
* to `[N items]` / `{ N keys }`. Never throws.
|
|
65
|
+
*/
|
|
66
|
+
export function formatValuePreview(value, options = {}) {
|
|
67
|
+
const maxLength = options.maxLength ?? 40;
|
|
68
|
+
if (value === undefined) return options.undefinedLabel ?? "undefined";
|
|
69
|
+
if (value === null) return "null";
|
|
70
|
+
try {
|
|
71
|
+
if (typeof value === "function") return options.functionLabel ?? "(fn)";
|
|
72
|
+
if (typeof value === "string") {
|
|
73
|
+
return value.length > maxLength ? `"${value.slice(0, maxLength - 3)}..."` : `"${value}"`;
|
|
74
|
+
}
|
|
75
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
76
|
+
return String(value);
|
|
77
|
+
}
|
|
78
|
+
if (Array.isArray(value)) {
|
|
79
|
+
if (value.length === 0) return "[]";
|
|
80
|
+
const preview = JSON.stringify(value);
|
|
81
|
+
return preview.length > maxLength ? `[${value.length} items]` : preview;
|
|
82
|
+
}
|
|
83
|
+
if (typeof value === "object") {
|
|
84
|
+
const keys = Object.keys(value);
|
|
85
|
+
if (keys.length === 0) return "{}";
|
|
86
|
+
const preview = JSON.stringify(value);
|
|
87
|
+
if (preview.length <= maxLength) return preview;
|
|
88
|
+
return `{ ${keys.length} keys }`;
|
|
89
|
+
}
|
|
90
|
+
return String(value).slice(0, maxLength);
|
|
91
|
+
} catch {
|
|
92
|
+
return "[complex]";
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ============================================
|
|
97
|
+
// Shallow diff summary
|
|
98
|
+
// ============================================
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Top-level, reference-equality diff between two states. Enough for a list
|
|
102
|
+
* row ("+1 ~2 keys"); the detail view runs the real tree diff.
|
|
103
|
+
*
|
|
104
|
+
* A state object that was REPLACED without any top-level value moving —
|
|
105
|
+
* exactly what zustand's persist middleware does when it rehydrates — is
|
|
106
|
+
* reported as `"nested change"` with no keys, never as one changed key with
|
|
107
|
+
* none named.
|
|
108
|
+
*/
|
|
109
|
+
export function shallowDiffSummary(prev, next) {
|
|
110
|
+
if (prev === next) {
|
|
111
|
+
return {
|
|
112
|
+
summary: "no change",
|
|
113
|
+
changedKeys: [],
|
|
114
|
+
changedCount: 0
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (typeof prev !== "object" || typeof next !== "object" || prev === null || next === null) {
|
|
118
|
+
return {
|
|
119
|
+
summary: "changed",
|
|
120
|
+
changedKeys: [],
|
|
121
|
+
changedCount: 0
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const prevRecord = prev;
|
|
125
|
+
const nextRecord = next;
|
|
126
|
+
const prevKeys = Object.keys(prevRecord);
|
|
127
|
+
const nextKeys = Object.keys(nextRecord);
|
|
128
|
+
const added = nextKeys.filter(k => !prevKeys.includes(k));
|
|
129
|
+
const removed = prevKeys.filter(k => !nextKeys.includes(k));
|
|
130
|
+
const changed = [];
|
|
131
|
+
for (const key of prevKeys) {
|
|
132
|
+
if (nextKeys.includes(key) && prevRecord[key] !== nextRecord[key]) {
|
|
133
|
+
changed.push(key);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const changedKeys = [...added, ...removed, ...changed];
|
|
137
|
+
const parts = [];
|
|
138
|
+
if (added.length > 0) parts.push(`+${added.length}`);
|
|
139
|
+
if (removed.length > 0) parts.push(`-${removed.length}`);
|
|
140
|
+
if (changed.length > 0) parts.push(`~${changed.length}`);
|
|
141
|
+
if (parts.length === 0) {
|
|
142
|
+
return {
|
|
143
|
+
summary: "nested change",
|
|
144
|
+
changedKeys: [],
|
|
145
|
+
changedCount: 0
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const total = changedKeys.length;
|
|
149
|
+
return {
|
|
150
|
+
summary: `${parts.join(" ")} ${total === 1 ? "key" : "keys"}`,
|
|
151
|
+
changedKeys,
|
|
152
|
+
changedCount: total
|
|
153
|
+
};
|
|
154
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsModal.d.ts","sourceRoot":"","sources":["../../../src/JsModal.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAUL,SAAS,EAEV,MAAM,OAAO,CAAC;AACf,OAAO,EAML,QAAQ,EAGR,SAAS,EAEV,MAAM,cAAc,CAAC;AAyHtB,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,UAAU,CAAC;AAEnD;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;AAE/C,UAAU,YAAY;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,UAAU,YAAY;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,kBAAkB,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACxD;AAED,UAAU,YAAY;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IAChC;;;+BAG2B;IAC3B,WAAW,CAAC,EAAE,QAAQ,GAAG,YAAY,GAAG,cAAc,GAAG,YAAY,CAAC;IACtE,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,uBAAuB,CAAC,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAErD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,yFAAyF;IACzF,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC9C,0EAA0E;IAC1E,sBAAsB,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC/B,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gIAAgI;IAChI,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iDAAiD;IACjD,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;
|
|
1
|
+
{"version":3,"file":"JsModal.d.ts","sourceRoot":"","sources":["../../../src/JsModal.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAUL,SAAS,EAEV,MAAM,OAAO,CAAC;AACf,OAAO,EAML,QAAQ,EAGR,SAAS,EAEV,MAAM,cAAc,CAAC;AAyHtB,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,UAAU,CAAC;AAEnD;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;AAE/C,UAAU,YAAY;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,UAAU,YAAY;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,kBAAkB,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACxD;AAED,UAAU,YAAY;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IAChC;;;+BAG2B;IAC3B,WAAW,CAAC,EAAE,QAAQ,GAAG,YAAY,GAAG,cAAc,GAAG,YAAY,CAAC;IACtE,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,uBAAuB,CAAC,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAErD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,yFAAyF;IACzF,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC9C,0EAA0E;IAC1E,sBAAsB,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC/B,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gIAAgI;IAChI,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iDAAiD;IACjD,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAo0DD,eAAO,MAAM,OAAO,oDAAyB,CAAC"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { useFilterManager } from "./useFilterManager";
|
|
2
|
-
export { usePersistedState } from "./usePersistedState";
|
|
2
|
+
export { usePersistedState, resetPersistedStateCache, type PersistedStateOptions, type PersistedStateStorage, } from "./usePersistedState";
|
|
3
|
+
export { useChangeLog, useSubscribedValue, type UseChangeLogOptions, type UseChangeLogResult, } from "./useChangeLog";
|
|
4
|
+
export { useEventStoreEvents, type UseEventStoreEventsOptions, type UseEventStoreEventsResult, } from "./useEventStoreEvents";
|
|
3
5
|
export { useSafeAreaInsets } from "./useSafeAreaInsets";
|
|
4
6
|
export { getSafeAreaInsets } from "./useSafeAreaInsets";
|
|
5
7
|
export { useDeviceInfo, getDeviceInfo, logDeviceInfo, type DeviceInfo, type PlatformInfo, type DisplayInfo, type AccessibilitySettings, type AppearanceInfo, type LocaleInfo, type StatusBarInfo, type KeyboardInfo, type AppStateInfo, type UniqueIdentifiers, type SettingsInfo, } from "./useDeviceInfo";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,mBAAmB,EACnB,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,GAC/B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,GAClB,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React bindings for `ChangeLog` — what useReduxActions, useZustandStateChanges
|
|
3
|
+
* and useJotaiAtomChanges each re-derived: seed state from the log, subscribe
|
|
4
|
+
* for the lifetime of the component, hold a filter, memoize the filtered
|
|
5
|
+
* list, and expose clear / pause / lookup.
|
|
6
|
+
*
|
|
7
|
+
* Tool-specific stats and registries (stores, atoms) compose on top — see
|
|
8
|
+
* `useSubscribedValue` for the registry half.
|
|
9
|
+
*/
|
|
10
|
+
import type { ChangeLog, Identified } from "../stores/ChangeLog";
|
|
11
|
+
export interface UseChangeLogOptions<T, F> {
|
|
12
|
+
/** Initial filter value. Default `{}`. */
|
|
13
|
+
initialFilter?: F;
|
|
14
|
+
/** Derive the filtered list. Default: identity (no filtering). */
|
|
15
|
+
filterItems?: (items: T[], filter: F) => T[];
|
|
16
|
+
}
|
|
17
|
+
export interface UseChangeLogResult<T, F> {
|
|
18
|
+
/** All recorded items, newest first. */
|
|
19
|
+
items: T[];
|
|
20
|
+
/** `items` after `filterItems`. */
|
|
21
|
+
filteredItems: T[];
|
|
22
|
+
filter: F;
|
|
23
|
+
setFilter: React.Dispatch<React.SetStateAction<F>>;
|
|
24
|
+
/** Whether recording is enabled (the pause button's state). */
|
|
25
|
+
isEnabled: boolean;
|
|
26
|
+
/** Flip recording on/off. */
|
|
27
|
+
toggleCapture: () => void;
|
|
28
|
+
/** Empty the log (fires the desktop mirror's clear forwarding). */
|
|
29
|
+
clear: () => void;
|
|
30
|
+
getById: (id: string) => T | undefined;
|
|
31
|
+
}
|
|
32
|
+
export declare function useChangeLog<T extends Identified, F extends object = Record<string, never>>(log: ChangeLog<T>, options?: UseChangeLogOptions<T, F>): UseChangeLogResult<T, F>;
|
|
33
|
+
/**
|
|
34
|
+
* Hold a value that a store pushes through a `(value) => void` listener —
|
|
35
|
+
* a registry of stores, atoms, sources. Seeded synchronously from `read`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function useSubscribedValue<V>(read: () => V, subscribe: (listener: (value: V) => void) => () => void): V;
|
|
38
|
+
//# sourceMappingURL=useChangeLog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useChangeLog.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useChangeLog.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjE,MAAM,WAAW,mBAAmB,CAAC,CAAC,EAAE,CAAC;IACvC,0CAA0C;IAC1C,aAAa,CAAC,EAAE,CAAC,CAAC;IAClB,kEAAkE;IAClE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC,EAAE,CAAC;IACtC,wCAAwC;IACxC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,mCAAmC;IACnC,aAAa,EAAE,CAAC,EAAE,CAAC;IACnB,MAAM,EAAE,CAAC,CAAC;IACV,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,+DAA+D;IAC/D,SAAS,EAAE,OAAO,CAAC;IACnB,6BAA6B;IAC7B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,mEAAmE;IACnE,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,CAAC,GAAG,SAAS,CAAC;CACxC;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EACzF,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,EACjB,OAAO,GAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAM,GACtC,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,CA0B1B;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,IAAI,EAAE,MAAM,CAAC,EACb,SAAS,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,KAAK,MAAM,IAAI,GACtD,CAAC,CAIH"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React bindings for a `BaseEventStore` — what useRouteEvents and
|
|
3
|
+
* useStorageEvents each hand-rolled: subscribe while enabled (which
|
|
4
|
+
* auto-starts the store's capture), coalesce bursts onto one animation
|
|
5
|
+
* frame so a storm of writes is one commit instead of one per emission,
|
|
6
|
+
* select/limit the list, and report whether capture is live.
|
|
7
|
+
*/
|
|
8
|
+
import type { BaseEventStore } from "../stores/BaseEventStore";
|
|
9
|
+
export interface UseEventStoreEventsOptions<T> {
|
|
10
|
+
/** Subscribe at all? `false` unsubscribes (and lets the store stop capturing). Default true. */
|
|
11
|
+
enabled?: boolean;
|
|
12
|
+
/** Cap the list handed to React. Default 500. */
|
|
13
|
+
maxEvents?: number;
|
|
14
|
+
/** Narrow the list before capping (a storage-type filter, say). */
|
|
15
|
+
select?: (events: T[]) => T[];
|
|
16
|
+
}
|
|
17
|
+
export interface UseEventStoreEventsResult<T> {
|
|
18
|
+
/** Newest first. */
|
|
19
|
+
events: T[];
|
|
20
|
+
clearEvents: () => void;
|
|
21
|
+
/** True while this hook holds a live subscription. */
|
|
22
|
+
isActive: boolean;
|
|
23
|
+
}
|
|
24
|
+
export declare function useEventStoreEvents<T>(store: BaseEventStore<T>, options?: UseEventStoreEventsOptions<T>): UseEventStoreEventsResult<T>;
|
|
25
|
+
//# sourceMappingURL=useEventStoreEvents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEventStoreEvents.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useEventStoreEvents.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,MAAM,WAAW,0BAA0B,CAAC,CAAC;IAC3C,gGAAgG;IAChG,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,yBAAyB,CAAC,CAAC;IAC1C,oBAAoB;IACpB,MAAM,EAAE,CAAC,EAAE,CAAC;IACZ,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,sDAAsD;IACtD,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,EACxB,OAAO,GAAE,0BAA0B,CAAC,CAAC,CAAM,GAC1C,yBAAyB,CAAC,CAAC,CAAC,CA8C9B"}
|
|
@@ -1,16 +1,45 @@
|
|
|
1
|
+
/** The two calls a backend needs. `persistentStorage` and AsyncStorage both fit. */
|
|
2
|
+
export interface PersistedStateStorage {
|
|
3
|
+
getItem(key: string): Promise<string | null>;
|
|
4
|
+
setItem(key: string, value: string): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
export interface PersistedStateOptions<T> {
|
|
7
|
+
/**
|
|
8
|
+
* Turn the stored string into a value. Return `undefined` to reject it
|
|
9
|
+
* (corrupt, or a value the UI no longer offers) and keep the default.
|
|
10
|
+
* Default: `JSON.parse`.
|
|
11
|
+
*/
|
|
12
|
+
parse?: (raw: string) => T | undefined;
|
|
13
|
+
/** Turn a value into the stored string. Default: `JSON.stringify`. */
|
|
14
|
+
serialize?: (value: T) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Where the value lives. Default: `persistentStorage` (FileSystem →
|
|
17
|
+
* AsyncStorage → memory). A tool whose keys were always written straight to
|
|
18
|
+
* AsyncStorage keeps reading them by passing AsyncStorage here.
|
|
19
|
+
*/
|
|
20
|
+
storage?: PersistedStateStorage;
|
|
21
|
+
}
|
|
1
22
|
/**
|
|
2
23
|
* `useState` persisted through `persistentStorage` (FileSystem → AsyncStorage
|
|
3
24
|
* → memory). Replaces the load-then-`hasLoaded`-guard `useEffect` pattern
|
|
4
25
|
* every tool used to hand-roll.
|
|
5
26
|
*
|
|
6
|
-
* Values are JSON-serialized; the default is returned until
|
|
7
|
-
* completes (subsequent mounts of the same key hydrate synchronously
|
|
8
|
-
* in-memory cache). The third tuple element reports hydration so
|
|
9
|
-
* defer writes that must not clobber a not-yet-loaded value.
|
|
27
|
+
* Values are JSON-serialized by default; the default is returned until
|
|
28
|
+
* hydration completes (subsequent mounts of the same key hydrate synchronously
|
|
29
|
+
* from an in-memory cache). The third tuple element reports hydration so
|
|
30
|
+
* callers can defer writes that must not clobber a not-yet-loaded value.
|
|
10
31
|
*
|
|
11
32
|
* ```tsx
|
|
12
33
|
* const [tab, setTab, tabHydrated] = usePersistedState("@react_buoy_custom_flags_tab", "flags");
|
|
34
|
+
*
|
|
35
|
+
* // A Set, stored as an array:
|
|
36
|
+
* const [pins, setPins] = usePersistedState(key, new Set<string>(), {
|
|
37
|
+
* parse: (raw) => new Set(JSON.parse(raw) as string[]),
|
|
38
|
+
* serialize: (set) => JSON.stringify([...set]),
|
|
39
|
+
* });
|
|
13
40
|
* ```
|
|
14
41
|
*/
|
|
15
|
-
export declare function usePersistedState<T>(key: string, defaultValue: T): [T, (next: T | ((prev: T) => T)) => void, boolean];
|
|
42
|
+
export declare function usePersistedState<T>(key: string, defaultValue: T, options?: PersistedStateOptions<T>): [T, (next: T | ((prev: T) => T)) => void, boolean];
|
|
43
|
+
/** Test seam: forget every hydrated value. */
|
|
44
|
+
export declare function resetPersistedStateCache(): void;
|
|
16
45
|
//# sourceMappingURL=usePersistedState.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePersistedState.d.ts","sourceRoot":"","sources":["../../../../src/hooks/usePersistedState.ts"],"names":[],"mappings":"AAUA
|
|
1
|
+
{"version":3,"file":"usePersistedState.d.ts","sourceRoot":"","sources":["../../../../src/hooks/usePersistedState.ts"],"names":[],"mappings":"AAUA,oFAAoF;AACpF,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACtC;;;;OAIG;IACH,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,SAAS,CAAC;IACvC,sEAAsE;IACtE,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,CAAC;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACjC;AAUD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,CAAC,EACf,OAAO,GAAE,qBAAqB,CAAC,CAAC,CAAM,GACrC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,EAAE,OAAO,CAAC,CA+DpD;AAED,8CAA8C;AAC9C,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|