@buoy-gg/shared-ui 7.0.33 → 7.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/lib/commonjs/JsModal.js +57 -22
  2. package/lib/commonjs/hooks/index.js +26 -0
  3. package/lib/commonjs/hooks/safe-area-impl.js +1 -1
  4. package/lib/commonjs/hooks/useChangeLog.js +55 -0
  5. package/lib/commonjs/hooks/useEventStoreEvents.js +65 -0
  6. package/lib/commonjs/hooks/usePersistedState.js +45 -10
  7. package/lib/commonjs/index.js +143 -0
  8. package/lib/commonjs/storage/definePersistedSetting.js +67 -0
  9. package/lib/commonjs/storage/index.js +8 -1
  10. package/lib/commonjs/stores/ChangeLog.js +197 -0
  11. package/lib/commonjs/stores/createToolStore.js +175 -0
  12. package/lib/commonjs/stores/index.js +15 -1
  13. package/lib/commonjs/sync/toolSyncAdapter.js +63 -0
  14. package/lib/commonjs/sync/wireForm.js +172 -0
  15. package/lib/commonjs/tools/defineTool.js +79 -0
  16. package/lib/commonjs/ui/components/ChangeRow.js +110 -0
  17. package/lib/commonjs/ui/components/ChipStrip.js +94 -0
  18. package/lib/commonjs/ui/components/DetailViewToggle.js +130 -0
  19. package/lib/commonjs/ui/components/DevToolsCard.js +3 -1
  20. package/lib/commonjs/ui/components/EntityFilterView.js +354 -0
  21. package/lib/commonjs/ui/components/ExportPreview.js +174 -0
  22. package/lib/commonjs/ui/components/InfoRow.js +90 -0
  23. package/lib/commonjs/ui/components/ModalHeader.js +40 -7
  24. package/lib/commonjs/ui/components/Pill.js +114 -0
  25. package/lib/commonjs/ui/components/ToggleRow.js +116 -0
  26. package/lib/commonjs/ui/components/ToolFooter.js +204 -0
  27. package/lib/commonjs/ui/components/index.js +100 -1
  28. package/lib/commonjs/ui/index.js +24 -2
  29. package/lib/commonjs/ui/listPresets.js +43 -0
  30. package/lib/commonjs/ui/night/primitives.js +3 -1
  31. package/lib/commonjs/utils/snapshotProviderKit.js +167 -0
  32. package/lib/commonjs/utils/stateTools.js +160 -0
  33. package/lib/module/JsModal.js +57 -22
  34. package/lib/module/hooks/index.js +3 -1
  35. package/lib/module/hooks/safe-area-impl.js +1 -1
  36. package/lib/module/hooks/useChangeLog.js +50 -0
  37. package/lib/module/hooks/useEventStoreEvents.js +61 -0
  38. package/lib/module/hooks/usePersistedState.js +44 -10
  39. package/lib/module/index.js +11 -1
  40. package/lib/module/storage/definePersistedSetting.js +63 -0
  41. package/lib/module/storage/index.js +2 -1
  42. package/lib/module/stores/ChangeLog.js +192 -0
  43. package/lib/module/stores/createToolStore.js +171 -0
  44. package/lib/module/stores/index.js +3 -1
  45. package/lib/module/sync/toolSyncAdapter.js +58 -0
  46. package/lib/module/sync/wireForm.js +159 -0
  47. package/lib/module/tools/defineTool.js +74 -0
  48. package/lib/module/ui/components/ChangeRow.js +105 -0
  49. package/lib/module/ui/components/ChipStrip.js +91 -0
  50. package/lib/module/ui/components/DetailViewToggle.js +125 -0
  51. package/lib/module/ui/components/DevToolsCard.js +3 -1
  52. package/lib/module/ui/components/EntityFilterView.js +350 -0
  53. package/lib/module/ui/components/ExportPreview.js +169 -0
  54. package/lib/module/ui/components/InfoRow.js +86 -0
  55. package/lib/module/ui/components/ModalHeader.js +40 -7
  56. package/lib/module/ui/components/Pill.js +110 -0
  57. package/lib/module/ui/components/ToggleRow.js +112 -0
  58. package/lib/module/ui/components/ToolFooter.js +196 -0
  59. package/lib/module/ui/components/index.js +10 -1
  60. package/lib/module/ui/index.js +4 -1
  61. package/lib/module/ui/listPresets.js +39 -0
  62. package/lib/module/ui/night/primitives.js +3 -1
  63. package/lib/module/utils/snapshotProviderKit.js +156 -0
  64. package/lib/module/utils/stateTools.js +154 -0
  65. package/lib/typescript/commonjs/JsModal.d.ts.map +1 -1
  66. package/lib/typescript/commonjs/hooks/index.d.ts +3 -1
  67. package/lib/typescript/commonjs/hooks/index.d.ts.map +1 -1
  68. package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
  69. package/lib/typescript/commonjs/hooks/useChangeLog.d.ts +38 -0
  70. package/lib/typescript/commonjs/hooks/useChangeLog.d.ts.map +1 -0
  71. package/lib/typescript/commonjs/hooks/useEventStoreEvents.d.ts +25 -0
  72. package/lib/typescript/commonjs/hooks/useEventStoreEvents.d.ts.map +1 -0
  73. package/lib/typescript/commonjs/hooks/usePersistedState.d.ts +34 -5
  74. package/lib/typescript/commonjs/hooks/usePersistedState.d.ts.map +1 -1
  75. package/lib/typescript/commonjs/index.d.ts +6 -1
  76. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  77. package/lib/typescript/commonjs/storage/definePersistedSetting.d.ts +39 -0
  78. package/lib/typescript/commonjs/storage/definePersistedSetting.d.ts.map +1 -0
  79. package/lib/typescript/commonjs/storage/index.d.ts +1 -0
  80. package/lib/typescript/commonjs/storage/index.d.ts.map +1 -1
  81. package/lib/typescript/commonjs/stores/ChangeLog.d.ts +100 -0
  82. package/lib/typescript/commonjs/stores/ChangeLog.d.ts.map +1 -0
  83. package/lib/typescript/commonjs/stores/createToolStore.d.ts +92 -0
  84. package/lib/typescript/commonjs/stores/createToolStore.d.ts.map +1 -0
  85. package/lib/typescript/commonjs/stores/index.d.ts +2 -0
  86. package/lib/typescript/commonjs/stores/index.d.ts.map +1 -1
  87. package/lib/typescript/commonjs/sync/toolSyncAdapter.d.ts +66 -0
  88. package/lib/typescript/commonjs/sync/toolSyncAdapter.d.ts.map +1 -0
  89. package/lib/typescript/commonjs/sync/wireForm.d.ts +100 -0
  90. package/lib/typescript/commonjs/sync/wireForm.d.ts.map +1 -0
  91. package/lib/typescript/commonjs/tools/defineTool.d.ts +100 -0
  92. package/lib/typescript/commonjs/tools/defineTool.d.ts.map +1 -0
  93. package/lib/typescript/commonjs/ui/components/ChangeRow.d.ts +52 -0
  94. package/lib/typescript/commonjs/ui/components/ChangeRow.d.ts.map +1 -0
  95. package/lib/typescript/commonjs/ui/components/ChipStrip.d.ts +41 -0
  96. package/lib/typescript/commonjs/ui/components/ChipStrip.d.ts.map +1 -0
  97. package/lib/typescript/commonjs/ui/components/DetailViewToggle.d.ts +36 -0
  98. package/lib/typescript/commonjs/ui/components/DetailViewToggle.d.ts.map +1 -0
  99. package/lib/typescript/commonjs/ui/components/DevToolsCard.d.ts +8 -1
  100. package/lib/typescript/commonjs/ui/components/DevToolsCard.d.ts.map +1 -1
  101. package/lib/typescript/commonjs/ui/components/EntityFilterView.d.ts +51 -0
  102. package/lib/typescript/commonjs/ui/components/EntityFilterView.d.ts.map +1 -0
  103. package/lib/typescript/commonjs/ui/components/ExportPreview.d.ts +48 -0
  104. package/lib/typescript/commonjs/ui/components/ExportPreview.d.ts.map +1 -0
  105. package/lib/typescript/commonjs/ui/components/InfoRow.d.ts +33 -0
  106. package/lib/typescript/commonjs/ui/components/InfoRow.d.ts.map +1 -0
  107. package/lib/typescript/commonjs/ui/components/ModalHeader.d.ts +31 -1
  108. package/lib/typescript/commonjs/ui/components/ModalHeader.d.ts.map +1 -1
  109. package/lib/typescript/commonjs/ui/components/Pill.d.ts +38 -0
  110. package/lib/typescript/commonjs/ui/components/Pill.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/ui/components/ToggleRow.d.ts +33 -0
  112. package/lib/typescript/commonjs/ui/components/ToggleRow.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/ui/components/ToolFooter.d.ts +69 -0
  114. package/lib/typescript/commonjs/ui/components/ToolFooter.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/ui/components/index.d.ts +9 -0
  116. package/lib/typescript/commonjs/ui/components/index.d.ts.map +1 -1
  117. package/lib/typescript/commonjs/ui/index.d.ts +1 -0
  118. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  119. package/lib/typescript/commonjs/ui/listPresets.d.ts +28 -0
  120. package/lib/typescript/commonjs/ui/listPresets.d.ts.map +1 -0
  121. package/lib/typescript/commonjs/ui/night/primitives.d.ts +3 -1
  122. package/lib/typescript/commonjs/ui/night/primitives.d.ts.map +1 -1
  123. package/lib/typescript/commonjs/utils/snapshotProviderKit.d.ts +81 -0
  124. package/lib/typescript/commonjs/utils/snapshotProviderKit.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/utils/stateTools.d.ts +44 -0
  126. package/lib/typescript/commonjs/utils/stateTools.d.ts.map +1 -0
  127. package/lib/typescript/module/JsModal.d.ts.map +1 -1
  128. package/lib/typescript/module/hooks/index.d.ts +3 -1
  129. package/lib/typescript/module/hooks/index.d.ts.map +1 -1
  130. package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
  131. package/lib/typescript/module/hooks/useChangeLog.d.ts +38 -0
  132. package/lib/typescript/module/hooks/useChangeLog.d.ts.map +1 -0
  133. package/lib/typescript/module/hooks/useEventStoreEvents.d.ts +25 -0
  134. package/lib/typescript/module/hooks/useEventStoreEvents.d.ts.map +1 -0
  135. package/lib/typescript/module/hooks/usePersistedState.d.ts +34 -5
  136. package/lib/typescript/module/hooks/usePersistedState.d.ts.map +1 -1
  137. package/lib/typescript/module/index.d.ts +6 -1
  138. package/lib/typescript/module/index.d.ts.map +1 -1
  139. package/lib/typescript/module/storage/definePersistedSetting.d.ts +39 -0
  140. package/lib/typescript/module/storage/definePersistedSetting.d.ts.map +1 -0
  141. package/lib/typescript/module/storage/index.d.ts +1 -0
  142. package/lib/typescript/module/storage/index.d.ts.map +1 -1
  143. package/lib/typescript/module/stores/ChangeLog.d.ts +100 -0
  144. package/lib/typescript/module/stores/ChangeLog.d.ts.map +1 -0
  145. package/lib/typescript/module/stores/createToolStore.d.ts +92 -0
  146. package/lib/typescript/module/stores/createToolStore.d.ts.map +1 -0
  147. package/lib/typescript/module/stores/index.d.ts +2 -0
  148. package/lib/typescript/module/stores/index.d.ts.map +1 -1
  149. package/lib/typescript/module/sync/toolSyncAdapter.d.ts +66 -0
  150. package/lib/typescript/module/sync/toolSyncAdapter.d.ts.map +1 -0
  151. package/lib/typescript/module/sync/wireForm.d.ts +100 -0
  152. package/lib/typescript/module/sync/wireForm.d.ts.map +1 -0
  153. package/lib/typescript/module/tools/defineTool.d.ts +100 -0
  154. package/lib/typescript/module/tools/defineTool.d.ts.map +1 -0
  155. package/lib/typescript/module/ui/components/ChangeRow.d.ts +52 -0
  156. package/lib/typescript/module/ui/components/ChangeRow.d.ts.map +1 -0
  157. package/lib/typescript/module/ui/components/ChipStrip.d.ts +41 -0
  158. package/lib/typescript/module/ui/components/ChipStrip.d.ts.map +1 -0
  159. package/lib/typescript/module/ui/components/DetailViewToggle.d.ts +36 -0
  160. package/lib/typescript/module/ui/components/DetailViewToggle.d.ts.map +1 -0
  161. package/lib/typescript/module/ui/components/DevToolsCard.d.ts +8 -1
  162. package/lib/typescript/module/ui/components/DevToolsCard.d.ts.map +1 -1
  163. package/lib/typescript/module/ui/components/EntityFilterView.d.ts +51 -0
  164. package/lib/typescript/module/ui/components/EntityFilterView.d.ts.map +1 -0
  165. package/lib/typescript/module/ui/components/ExportPreview.d.ts +48 -0
  166. package/lib/typescript/module/ui/components/ExportPreview.d.ts.map +1 -0
  167. package/lib/typescript/module/ui/components/InfoRow.d.ts +33 -0
  168. package/lib/typescript/module/ui/components/InfoRow.d.ts.map +1 -0
  169. package/lib/typescript/module/ui/components/ModalHeader.d.ts +31 -1
  170. package/lib/typescript/module/ui/components/ModalHeader.d.ts.map +1 -1
  171. package/lib/typescript/module/ui/components/Pill.d.ts +38 -0
  172. package/lib/typescript/module/ui/components/Pill.d.ts.map +1 -0
  173. package/lib/typescript/module/ui/components/ToggleRow.d.ts +33 -0
  174. package/lib/typescript/module/ui/components/ToggleRow.d.ts.map +1 -0
  175. package/lib/typescript/module/ui/components/ToolFooter.d.ts +69 -0
  176. package/lib/typescript/module/ui/components/ToolFooter.d.ts.map +1 -0
  177. package/lib/typescript/module/ui/components/index.d.ts +9 -0
  178. package/lib/typescript/module/ui/components/index.d.ts.map +1 -1
  179. package/lib/typescript/module/ui/index.d.ts +1 -0
  180. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  181. package/lib/typescript/module/ui/listPresets.d.ts +28 -0
  182. package/lib/typescript/module/ui/listPresets.d.ts.map +1 -0
  183. package/lib/typescript/module/ui/night/primitives.d.ts +3 -1
  184. package/lib/typescript/module/ui/night/primitives.d.ts.map +1 -1
  185. package/lib/typescript/module/utils/snapshotProviderKit.d.ts +81 -0
  186. package/lib/typescript/module/utils/snapshotProviderKit.d.ts.map +1 -0
  187. package/lib/typescript/module/utils/stateTools.d.ts +44 -0
  188. package/lib/typescript/module/utils/stateTools.d.ts.map +1 -0
  189. package/package.json +4 -4
@@ -606,7 +606,6 @@ const JsModalComponent = ({
606
606
  // ============================================================================
607
607
  // REFS for values we need to track
608
608
  // ============================================================================
609
- const isExternallyControlled = !!externalAnimatedHeight;
610
609
  const effectiveMaxHeight = maxHeight || SCREEN.height - insets.top;
611
610
 
612
611
  // Mode toggle handler
@@ -728,29 +727,57 @@ const JsModalComponent = ({
728
727
  // ============================================================================
729
728
  // EFFECT: Visibility Animations - All using native driver!
730
729
  // ============================================================================
730
+ const snapVisibility = shown => {
731
+ if (shown) {
732
+ if (mode === "bottomSheet") {
733
+ bottomSheetTranslateY.setValue(0);
734
+ } else {
735
+ floatingScale.setValue(1);
736
+ floatingPosition.setValue({
737
+ x: currentDimensionsRef.current.left,
738
+ y: currentDimensionsRef.current.top
739
+ });
740
+ }
741
+ visibilityProgress.setValue(1);
742
+ } else {
743
+ if (mode === "bottomSheet") {
744
+ bottomSheetTranslateY.setValue(SCREEN.height);
745
+ }
746
+ visibilityProgress.setValue(0);
747
+ }
748
+ };
749
+
750
+ /**
751
+ * Snap DURING RENDER when `visible` flips, not only in the effect below.
752
+ *
753
+ * These values drive the sheet's opacity/translate through the native
754
+ * driver. The React commit for a `visible` change carries whatever the
755
+ * JS-side values are at render time — the OLD, hidden ones when the snap
756
+ * only happens in the effect — and on Fabric that commit's mount can land
757
+ * on the main thread AFTER the effect's native `setValue`, overwriting it.
758
+ * The Animated node then says "shown" while the UIView sits at opacity 0,
759
+ * until some unrelated re-render commits the JS-side values again. That
760
+ * is how "restore tool A: nothing; restore tool B: A appears; hide B: now
761
+ * B appears" happened — every restore was one commit behind.
762
+ *
763
+ * Setting the values before the render's props are computed makes the
764
+ * commit and the native node agree, whichever lands last. `setValue` is
765
+ * idempotent, so a re-run render is harmless.
766
+ */
767
+ const snappedVisibleRef = (0, _react.useRef)(null);
768
+ if (INSTANT_MODAL_ENTRANCE && snappedVisibleRef.current !== visible) {
769
+ snappedVisibleRef.current = visible;
770
+ snapVisibility(visible);
771
+ }
731
772
  (0, _react.useEffect)(() => {
732
773
  // Visibility effect
733
774
  let openAnimation = null;
734
775
  let closeAnimation = null;
735
776
  if (INSTANT_MODAL_ENTRANCE) {
736
- // Snap to the final state — no animation in either direction.
737
- if (visible) {
738
- if (mode === "bottomSheet") {
739
- bottomSheetTranslateY.setValue(0);
740
- } else {
741
- floatingScale.setValue(1);
742
- floatingPosition.setValue({
743
- x: currentDimensionsRef.current.left,
744
- y: currentDimensionsRef.current.top
745
- });
746
- }
747
- visibilityProgress.setValue(1);
748
- } else {
749
- if (mode === "bottomSheet") {
750
- bottomSheetTranslateY.setValue(SCREEN.height);
751
- }
752
- visibilityProgress.setValue(0);
753
- }
777
+ // Snap to the final state — no animation in either direction. The
778
+ // render-phase snap above already did this for a `visible` flip; this
779
+ // re-applies it for a `mode` change while shown.
780
+ snapVisibility(visible);
754
781
  return;
755
782
  }
756
783
  if (visible) {
@@ -915,8 +942,15 @@ const JsModalComponent = ({
915
942
  // eslint-disable-next-line react-hooks/exhaustive-deps
916
943
  }, [benchMotion, visible]);
917
944
  const bottomSheetPanResponder = (0, _react.useMemo)(() => _reactNative.PanResponder.create({
918
- onStartShouldSetPanResponder: () => !isExternallyControlled && mode === "bottomSheet",
919
- onMoveShouldSetPanResponder: (evt, gestureState) => !isExternallyControlled && mode === "bottomSheet" && Math.abs(gestureState.dy) > 3,
945
+ // An external `animatedHeight` used to disable this responder
946
+ // outright ("externally controlled"), which left Ask Buoy's sheet —
947
+ // the one host that passes one, for its peek animation — with a
948
+ // header that could not be dragged in bottom-sheet mode. The move
949
+ // and release handlers below already write every height into the
950
+ // external value, so the host and the finger share one number; the
951
+ // grab just has to stop whatever the host is animating first.
952
+ onStartShouldSetPanResponder: () => mode === "bottomSheet",
953
+ onMoveShouldSetPanResponder: (evt, gestureState) => mode === "bottomSheet" && Math.abs(gestureState.dy) > 3,
920
954
  onPanResponderTerminationRequest: () => false,
921
955
  onPanResponderGrant: evt => {
922
956
  setIsResizing(true);
@@ -928,6 +962,7 @@ const JsModalComponent = ({
928
962
  animatedBottomPosition.stopAnimation(val => {
929
963
  currentHeightRef.current = val;
930
964
  });
965
+ externalAnimatedHeight?.stopAnimation();
931
966
  bottomSheetTranslateY.stopAnimation();
932
967
  },
933
968
  onPanResponderMove: evt => {
@@ -974,7 +1009,7 @@ const JsModalComponent = ({
974
1009
  setIsResizing(false);
975
1010
  // snap back to the last stable height if you want; otherwise no-op
976
1011
  }
977
- }), [mode, isExternallyControlled, minHeight, effectiveMaxHeight, animatedBottomPosition, externalAnimatedHeight, bottomSheetTranslateY, visibilityProgress, onClose]);
1012
+ }), [mode, minHeight, effectiveMaxHeight, animatedBottomPosition, externalAnimatedHeight, bottomSheetTranslateY, visibilityProgress, onClose]);
978
1013
 
979
1014
  // ============================================================================
980
1015
  // CREATE RESIZE HANDLER: For 4-corner resize in floating mode (fixed geometry)
@@ -21,12 +21,30 @@ Object.defineProperty(exports, "logDeviceInfo", {
21
21
  return _useDeviceInfo.logDeviceInfo;
22
22
  }
23
23
  });
24
+ Object.defineProperty(exports, "resetPersistedStateCache", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _usePersistedState.resetPersistedStateCache;
28
+ }
29
+ });
30
+ Object.defineProperty(exports, "useChangeLog", {
31
+ enumerable: true,
32
+ get: function () {
33
+ return _useChangeLog.useChangeLog;
34
+ }
35
+ });
24
36
  Object.defineProperty(exports, "useDeviceInfo", {
25
37
  enumerable: true,
26
38
  get: function () {
27
39
  return _useDeviceInfo.useDeviceInfo;
28
40
  }
29
41
  });
42
+ Object.defineProperty(exports, "useEventStoreEvents", {
43
+ enumerable: true,
44
+ get: function () {
45
+ return _useEventStoreEvents.useEventStoreEvents;
46
+ }
47
+ });
30
48
  Object.defineProperty(exports, "useFilterManager", {
31
49
  enumerable: true,
32
50
  get: function () {
@@ -45,7 +63,15 @@ Object.defineProperty(exports, "useSafeAreaInsets", {
45
63
  return _useSafeAreaInsets.useSafeAreaInsets;
46
64
  }
47
65
  });
66
+ Object.defineProperty(exports, "useSubscribedValue", {
67
+ enumerable: true,
68
+ get: function () {
69
+ return _useChangeLog.useSubscribedValue;
70
+ }
71
+ });
48
72
  var _useFilterManager = require("./useFilterManager.js");
49
73
  var _usePersistedState = require("./usePersistedState.js");
74
+ var _useChangeLog = require("./useChangeLog.js");
75
+ var _useEventStoreEvents = require("./useEventStoreEvents.js");
50
76
  var _useSafeAreaInsets = require("./useSafeAreaInsets.js");
51
77
  var _useDeviceInfo = require("./useDeviceInfo.js");
@@ -7,7 +7,7 @@ exports.useNativeSafeAreaInsets = exports.safeAreaType = exports.hasSafeAreaPack
7
7
  /**
8
8
  * Auto-generated safe area implementation
9
9
  * Detected: none
10
- * Generated at: 2026-09-02T23:25:39.783Z
10
+ * Generated at: 2026-09-04T01:21:28.486Z
11
11
  *
12
12
  * DO NOT EDIT - This file is generated by scripts/detect-safe-area.js
13
13
  *
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useChangeLog = useChangeLog;
7
+ exports.useSubscribedValue = useSubscribedValue;
8
+ var _react = require("react");
9
+ /**
10
+ * React bindings for `ChangeLog` — what useReduxActions, useZustandStateChanges
11
+ * and useJotaiAtomChanges each re-derived: seed state from the log, subscribe
12
+ * for the lifetime of the component, hold a filter, memoize the filtered
13
+ * list, and expose clear / pause / lookup.
14
+ *
15
+ * Tool-specific stats and registries (stores, atoms) compose on top — see
16
+ * `useSubscribedValue` for the registry half.
17
+ */
18
+
19
+ function useChangeLog(log, options = {}) {
20
+ const [items, setItems] = (0, _react.useState)(() => log.getAll());
21
+ const [filter, setFilter] = (0, _react.useState)(() => options.initialFilter ?? {});
22
+ const [isEnabled, setIsEnabled] = (0, _react.useState)(() => log.getEnabled());
23
+ (0, _react.useEffect)(() => log.subscribe(setItems), [log]);
24
+ const filterItems = options.filterItems;
25
+ const filteredItems = (0, _react.useMemo)(() => filterItems ? filterItems(items, filter) : items, [items, filter, filterItems]);
26
+ const clear = (0, _react.useCallback)(() => {
27
+ log.clear();
28
+ }, [log]);
29
+ const toggleCapture = (0, _react.useCallback)(() => {
30
+ const next = !isEnabled;
31
+ log.setEnabled(next);
32
+ setIsEnabled(next);
33
+ }, [log, isEnabled]);
34
+ const getById = (0, _react.useCallback)(id => log.getById(id), [log]);
35
+ return {
36
+ items,
37
+ filteredItems,
38
+ filter,
39
+ setFilter,
40
+ isEnabled,
41
+ toggleCapture,
42
+ clear,
43
+ getById
44
+ };
45
+ }
46
+
47
+ /**
48
+ * Hold a value that a store pushes through a `(value) => void` listener —
49
+ * a registry of stores, atoms, sources. Seeded synchronously from `read`.
50
+ */
51
+ function useSubscribedValue(read, subscribe) {
52
+ const [value, setValue] = (0, _react.useState)(read);
53
+ (0, _react.useEffect)(() => subscribe(setValue), [subscribe]);
54
+ return value;
55
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useEventStoreEvents = useEventStoreEvents;
7
+ var _react = require("react");
8
+ /**
9
+ * React bindings for a `BaseEventStore` — what useRouteEvents and
10
+ * useStorageEvents each hand-rolled: subscribe while enabled (which
11
+ * auto-starts the store's capture), coalesce bursts onto one animation
12
+ * frame so a storm of writes is one commit instead of one per emission,
13
+ * select/limit the list, and report whether capture is live.
14
+ */
15
+
16
+ function useEventStoreEvents(store, options = {}) {
17
+ const {
18
+ enabled = true,
19
+ maxEvents = 500,
20
+ select
21
+ } = options;
22
+ const [events, setEvents] = (0, _react.useState)([]);
23
+ // Tracked locally so it updates reactively with the subscription.
24
+ const [isActive, setIsActive] = (0, _react.useState)(enabled);
25
+ (0, _react.useEffect)(() => {
26
+ if (!enabled) {
27
+ setIsActive(false);
28
+ return;
29
+ }
30
+
31
+ // Frame-coalesced: bursts land as ONE commit per frame instead of one
32
+ // per emission — the dominant live-churn cost measured on the network
33
+ // tool (tool-bench 2026-07-06).
34
+ let rafId = null;
35
+ let pending = null;
36
+ const unsubscribe = store.subscribeToEvents(all => {
37
+ pending = all;
38
+ if (rafId != null) return;
39
+ rafId = requestAnimationFrame(() => {
40
+ rafId = null;
41
+ if (!pending) return;
42
+ let next = pending;
43
+ pending = null;
44
+ if (select) next = select(next);
45
+ if (next.length > maxEvents) next = next.slice(0, maxEvents);
46
+ setEvents(next);
47
+ });
48
+ });
49
+ setIsActive(true);
50
+ return () => {
51
+ unsubscribe();
52
+ if (rafId != null) cancelAnimationFrame(rafId);
53
+ // Not setting isActive=false here: a dependency change re-subscribes
54
+ // immediately, and that is not "stopped".
55
+ };
56
+ }, [store, enabled, maxEvents, select]);
57
+ const clearEvents = (0, _react.useCallback)(() => {
58
+ store.clearEvents();
59
+ }, [store]);
60
+ return {
61
+ events,
62
+ clearEvents,
63
+ isActive
64
+ };
65
+ }
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.resetPersistedStateCache = resetPersistedStateCache;
6
7
  exports.usePersistedState = usePersistedState;
7
8
  var _react = require("react");
8
9
  var _persistentStorage = require("../utils/persistentStorage.js");
@@ -13,25 +14,43 @@ var _persistentStorage = require("../utils/persistentStorage.js");
13
14
  */
14
15
  const hydratedCache = new Map();
15
16
 
17
+ /** The two calls a backend needs. `persistentStorage` and AsyncStorage both fit. */
18
+
19
+ function defaultParse(raw) {
20
+ try {
21
+ return JSON.parse(raw);
22
+ } catch {
23
+ return undefined;
24
+ }
25
+ }
26
+
16
27
  /**
17
28
  * `useState` persisted through `persistentStorage` (FileSystem → AsyncStorage
18
29
  * → memory). Replaces the load-then-`hasLoaded`-guard `useEffect` pattern
19
30
  * every tool used to hand-roll.
20
31
  *
21
- * Values are JSON-serialized; the default is returned until hydration
22
- * completes (subsequent mounts of the same key hydrate synchronously from an
23
- * in-memory cache). The third tuple element reports hydration so callers can
24
- * defer writes that must not clobber a not-yet-loaded value.
32
+ * Values are JSON-serialized by default; the default is returned until
33
+ * hydration completes (subsequent mounts of the same key hydrate synchronously
34
+ * from an in-memory cache). The third tuple element reports hydration so
35
+ * callers can defer writes that must not clobber a not-yet-loaded value.
25
36
  *
26
37
  * ```tsx
27
38
  * const [tab, setTab, tabHydrated] = usePersistedState("@react_buoy_custom_flags_tab", "flags");
39
+ *
40
+ * // A Set, stored as an array:
41
+ * const [pins, setPins] = usePersistedState(key, new Set<string>(), {
42
+ * parse: (raw) => new Set(JSON.parse(raw) as string[]),
43
+ * serialize: (set) => JSON.stringify([...set]),
44
+ * });
28
45
  * ```
29
46
  */
30
- function usePersistedState(key, defaultValue) {
47
+ function usePersistedState(key, defaultValue, options = {}) {
31
48
  const [value, setValue] = (0, _react.useState)(() => hydratedCache.has(key) ? hydratedCache.get(key) : defaultValue);
32
49
  const [hydrated, setHydrated] = (0, _react.useState)(() => hydratedCache.has(key));
33
50
  const keyRef = (0, _react.useRef)(key);
34
51
  keyRef.current = key;
52
+ const optionsRef = (0, _react.useRef)(options);
53
+ optionsRef.current = options;
35
54
  (0, _react.useEffect)(() => {
36
55
  if (hydratedCache.has(key)) {
37
56
  setValue(hydratedCache.get(key));
@@ -39,17 +58,22 @@ function usePersistedState(key, defaultValue) {
39
58
  return;
40
59
  }
41
60
  let cancelled = false;
42
- _persistentStorage.persistentStorage.getItem(key).then(raw => {
61
+ const storage = optionsRef.current.storage ?? _persistentStorage.persistentStorage;
62
+ const parse = optionsRef.current.parse ?? defaultParse;
63
+ storage.getItem(key).then(raw => {
43
64
  if (cancelled) return;
44
65
  if (raw != null) {
66
+ let parsed;
45
67
  try {
46
- const parsed = JSON.parse(raw);
47
- hydratedCache.set(key, parsed);
48
- setValue(parsed);
68
+ parsed = parse(raw);
49
69
  } catch {
50
70
  // Corrupt payload — fall back to the default and let the next
51
71
  // write repair it.
52
72
  }
73
+ if (parsed !== undefined) {
74
+ hydratedCache.set(key, parsed);
75
+ setValue(parsed);
76
+ }
53
77
  }
54
78
  setHydrated(true);
55
79
  }).catch(() => {
@@ -63,9 +87,20 @@ function usePersistedState(key, defaultValue) {
63
87
  setValue(prev => {
64
88
  const resolved = typeof next === "function" ? next(prev) : next;
65
89
  hydratedCache.set(keyRef.current, resolved);
66
- _persistentStorage.persistentStorage.setItem(keyRef.current, JSON.stringify(resolved)).catch(() => {});
90
+ const storage = optionsRef.current.storage ?? _persistentStorage.persistentStorage;
91
+ const serialize = optionsRef.current.serialize ?? JSON.stringify;
92
+ try {
93
+ storage.setItem(keyRef.current, serialize(resolved)).catch(() => {});
94
+ } catch {
95
+ // Unserializable value — keep it in memory, skip the write.
96
+ }
67
97
  return resolved;
68
98
  });
69
99
  }, []);
70
100
  return [value, set, hydrated];
101
+ }
102
+
103
+ /** Test seam: forget every hydrated value. */
104
+ function resetPersistedStateCache() {
105
+ hydratedCache.clear();
71
106
  }
@@ -52,10 +52,25 @@ var _exportNames = {
52
52
  getSafeCurrentPathname: true,
53
53
  getSafeCurrentRoute: true,
54
54
  isExpoRouterAvailable: true,
55
+ PREVIEW_ITEM_RENDER_BYTE_LIMIT: true,
56
+ createRestoreScope: true,
57
+ emptyRestoreResult: true,
58
+ failedRestore: true,
59
+ skippedRestore: true,
60
+ classifyPreviewItem: true,
61
+ wontApply: true,
62
+ unionKeys: true,
63
+ entityColor: true,
64
+ formatValuePreview: true,
65
+ shallowDiffSummary: true,
55
66
  isPlainObjectUtil: true,
56
67
  useSafeAreaInsets: true,
57
68
  useFilterManager: true,
58
69
  usePersistedState: true,
70
+ resetPersistedStateCache: true,
71
+ useChangeLog: true,
72
+ useSubscribedValue: true,
73
+ useEventStoreEvents: true,
59
74
  useDeviceInfo: true,
60
75
  getDeviceInfo: true,
61
76
  logDeviceInfo: true,
@@ -222,6 +237,12 @@ Object.defineProperty(exports, "NightSwitch", {
222
237
  return _primitives.NightSwitch;
223
238
  }
224
239
  });
240
+ Object.defineProperty(exports, "PREVIEW_ITEM_RENDER_BYTE_LIMIT", {
241
+ enumerable: true,
242
+ get: function () {
243
+ return _snapshotProviderKit.PREVIEW_ITEM_RENDER_BYTE_LIMIT;
244
+ }
245
+ });
225
246
  Object.defineProperty(exports, "ProBadge", {
226
247
  enumerable: true,
227
248
  get: function () {
@@ -282,6 +303,18 @@ Object.defineProperty(exports, "buoyColors", {
282
303
  return _gameUIColors.buoyColors;
283
304
  }
284
305
  });
306
+ Object.defineProperty(exports, "classifyPreviewItem", {
307
+ enumerable: true,
308
+ get: function () {
309
+ return _snapshotProviderKit.classifyPreviewItem;
310
+ }
311
+ });
312
+ Object.defineProperty(exports, "createRestoreScope", {
313
+ enumerable: true,
314
+ get: function () {
315
+ return _snapshotProviderKit.createRestoreScope;
316
+ }
317
+ });
285
318
  Object.defineProperty(exports, "dialColors", {
286
319
  enumerable: true,
287
320
  get: function () {
@@ -294,6 +327,24 @@ Object.defineProperty(exports, "displayValue", {
294
327
  return _index3.displayValue;
295
328
  }
296
329
  });
330
+ Object.defineProperty(exports, "emptyRestoreResult", {
331
+ enumerable: true,
332
+ get: function () {
333
+ return _snapshotProviderKit.emptyRestoreResult;
334
+ }
335
+ });
336
+ Object.defineProperty(exports, "entityColor", {
337
+ enumerable: true,
338
+ get: function () {
339
+ return _stateTools.entityColor;
340
+ }
341
+ });
342
+ Object.defineProperty(exports, "failedRestore", {
343
+ enumerable: true,
344
+ get: function () {
345
+ return _snapshotProviderKit.failedRestore;
346
+ }
347
+ });
297
348
  Object.defineProperty(exports, "flattenObject", {
298
349
  enumerable: true,
299
350
  get: function () {
@@ -312,6 +363,12 @@ Object.defineProperty(exports, "formatValue", {
312
363
  return _index3.formatValue;
313
364
  }
314
365
  });
366
+ Object.defineProperty(exports, "formatValuePreview", {
367
+ enumerable: true,
368
+ get: function () {
369
+ return _stateTools.formatValuePreview;
370
+ }
371
+ });
315
372
  Object.defineProperty(exports, "freeKeyRaises", {
316
373
  enumerable: true,
317
374
  get: function () {
@@ -546,6 +603,12 @@ Object.defineProperty(exports, "reloadApp", {
546
603
  return _index3.reloadApp;
547
604
  }
548
605
  });
606
+ Object.defineProperty(exports, "resetPersistedStateCache", {
607
+ enumerable: true,
608
+ get: function () {
609
+ return _index1.resetPersistedStateCache;
610
+ }
611
+ });
549
612
  Object.defineProperty(exports, "resolveEffectiveTier", {
550
613
  enumerable: true,
551
614
  get: function () {
@@ -576,6 +639,18 @@ Object.defineProperty(exports, "setRenderCaptureProvider", {
576
639
  return _index3.setRenderCaptureProvider;
577
640
  }
578
641
  });
642
+ Object.defineProperty(exports, "shallowDiffSummary", {
643
+ enumerable: true,
644
+ get: function () {
645
+ return _stateTools.shallowDiffSummary;
646
+ }
647
+ });
648
+ Object.defineProperty(exports, "skippedRestore", {
649
+ enumerable: true,
650
+ get: function () {
651
+ return _snapshotProviderKit.skippedRestore;
652
+ }
653
+ });
579
654
  Object.defineProperty(exports, "subscribeToStateSnapshotProviders", {
580
655
  enumerable: true,
581
656
  get: function () {
@@ -612,12 +687,30 @@ Object.defineProperty(exports, "truncateText", {
612
687
  return _index3.truncateText;
613
688
  }
614
689
  });
690
+ Object.defineProperty(exports, "unionKeys", {
691
+ enumerable: true,
692
+ get: function () {
693
+ return _snapshotProviderKit.unionKeys;
694
+ }
695
+ });
696
+ Object.defineProperty(exports, "useChangeLog", {
697
+ enumerable: true,
698
+ get: function () {
699
+ return _index1.useChangeLog;
700
+ }
701
+ });
615
702
  Object.defineProperty(exports, "useDeviceInfo", {
616
703
  enumerable: true,
617
704
  get: function () {
618
705
  return _index1.useDeviceInfo;
619
706
  }
620
707
  });
708
+ Object.defineProperty(exports, "useEventStoreEvents", {
709
+ enumerable: true,
710
+ get: function () {
711
+ return _index1.useEventStoreEvents;
712
+ }
713
+ });
621
714
  Object.defineProperty(exports, "useFeatureGate", {
622
715
  enumerable: true,
623
716
  get: function () {
@@ -684,6 +777,18 @@ Object.defineProperty(exports, "useSafeSegments", {
684
777
  return _index3.useSafeSegments;
685
778
  }
686
779
  });
780
+ Object.defineProperty(exports, "useSubscribedValue", {
781
+ enumerable: true,
782
+ get: function () {
783
+ return _index1.useSubscribedValue;
784
+ }
785
+ });
786
+ Object.defineProperty(exports, "wontApply", {
787
+ enumerable: true,
788
+ get: function () {
789
+ return _snapshotProviderKit.wontApply;
790
+ }
791
+ });
687
792
  var _index = require("./ui/index.js");
688
793
  Object.keys(_index).forEach(function (key) {
689
794
  if (key === "default" || key === "__esModule") return;
@@ -720,6 +825,42 @@ Object.keys(_wireBudget).forEach(function (key) {
720
825
  }
721
826
  });
722
827
  });
828
+ var _wireForm = require("./sync/wireForm.js");
829
+ Object.keys(_wireForm).forEach(function (key) {
830
+ if (key === "default" || key === "__esModule") return;
831
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
832
+ if (key in exports && exports[key] === _wireForm[key]) return;
833
+ Object.defineProperty(exports, key, {
834
+ enumerable: true,
835
+ get: function () {
836
+ return _wireForm[key];
837
+ }
838
+ });
839
+ });
840
+ var _toolSyncAdapter = require("./sync/toolSyncAdapter.js");
841
+ Object.keys(_toolSyncAdapter).forEach(function (key) {
842
+ if (key === "default" || key === "__esModule") return;
843
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
844
+ if (key in exports && exports[key] === _toolSyncAdapter[key]) return;
845
+ Object.defineProperty(exports, key, {
846
+ enumerable: true,
847
+ get: function () {
848
+ return _toolSyncAdapter[key];
849
+ }
850
+ });
851
+ });
852
+ var _defineTool = require("./tools/defineTool.js");
853
+ Object.keys(_defineTool).forEach(function (key) {
854
+ if (key === "default" || key === "__esModule") return;
855
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
856
+ if (key in exports && exports[key] === _defineTool[key]) return;
857
+ Object.defineProperty(exports, key, {
858
+ enumerable: true,
859
+ get: function () {
860
+ return _defineTool[key];
861
+ }
862
+ });
863
+ });
723
864
  var _toolActionRegistry = require("./sync/toolActionRegistry.js");
724
865
  Object.keys(_toolActionRegistry).forEach(function (key) {
725
866
  if (key === "default" || key === "__esModule") return;
@@ -745,6 +886,8 @@ Object.keys(_toolUiBridge).forEach(function (key) {
745
886
  });
746
887
  });
747
888
  var _index3 = require("./utils/index.js");
889
+ var _snapshotProviderKit = require("./utils/snapshotProviderKit.js");
890
+ var _stateTools = require("./utils/stateTools.js");
748
891
  var _index4 = require("./utils/formatting/index.js");
749
892
  Object.keys(_index4).forEach(function (key) {
750
893
  if (key === "default" || key === "__esModule") return;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.definePersistedSetting = definePersistedSetting;
7
+ var _persistentStorage = require("../utils/persistentStorage.js");
8
+ /**
9
+ * definePersistedSetting — the `load / save / clear` triple every tool wrote
10
+ * for its module-level settings (copy settings, HUD prefs, JS TOP prefs, …).
11
+ *
12
+ * Contract, the same one all of them followed:
13
+ * - `load()` never throws and never returns a partial object: the stored
14
+ * value is merged OVER the defaults so fields added in a later release
15
+ * get their default instead of `undefined`, then `sanitize` gets the last
16
+ * word (drop values the UI no longer offers, coerce types).
17
+ * - `save()` and `clear()` are best-effort; persistence is optional.
18
+ * - `loadOrNull()` distinguishes "nothing saved yet" from the defaults, for
19
+ * callers that treat first launch differently.
20
+ */
21
+
22
+ function isPlainObject(value) {
23
+ return typeof value === "object" && value !== null && !Array.isArray(value);
24
+ }
25
+ function definePersistedSetting(key, defaults, options = {}) {
26
+ const storage = options.storage ?? _persistentStorage.persistentStorage;
27
+ const parse = options.parse ?? (raw => JSON.parse(raw));
28
+ const serialize = options.serialize ?? (value => JSON.stringify(value));
29
+ function resolve(stored) {
30
+ const merged = isPlainObject(defaults) && isPlainObject(stored) ? {
31
+ ...defaults,
32
+ ...stored
33
+ } : stored;
34
+ return options.sanitize ? options.sanitize(merged, stored) : merged;
35
+ }
36
+ async function loadOrNull() {
37
+ try {
38
+ const raw = await storage.getItem(key);
39
+ if (raw == null || raw === "") return null;
40
+ return resolve(parse(raw));
41
+ } catch {
42
+ return null;
43
+ }
44
+ }
45
+ return {
46
+ key,
47
+ defaults,
48
+ loadOrNull,
49
+ async load() {
50
+ return (await loadOrNull()) ?? defaults;
51
+ },
52
+ async save(value) {
53
+ try {
54
+ await storage.setItem(key, serialize(value));
55
+ } catch {
56
+ // Persistence is best-effort.
57
+ }
58
+ },
59
+ async clear() {
60
+ try {
61
+ await storage.removeItem(key);
62
+ } catch {
63
+ // Persistence is best-effort.
64
+ }
65
+ }
66
+ };
67
+ }