@buoy-gg/zustand 5.0.0 → 6.0.0

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.
@@ -380,10 +380,10 @@ function ZustandModal({
380
380
  contentContainerStyle: styles.listContent,
381
381
  showsVerticalScrollIndicator: true,
382
382
  removeClippedSubviews: true,
383
- initialNumToRender: 15,
384
- maxToRenderPerBatch: 10,
385
- windowSize: 10,
386
- scrollEnabled: false
383
+ initialNumToRender: 12,
384
+ maxToRenderPerBatch: 8,
385
+ windowSize: 5,
386
+ updateCellsBatchingPeriod: 50
387
387
  }) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
388
388
  style: styles.emptyState,
389
389
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Box, {
@@ -444,10 +444,10 @@ function ZustandModal({
444
444
  contentContainerStyle: styles.listContent,
445
445
  showsVerticalScrollIndicator: true,
446
446
  removeClippedSubviews: true,
447
- initialNumToRender: 15,
448
- maxToRenderPerBatch: 10,
449
- windowSize: 10,
450
- scrollEnabled: false
447
+ initialNumToRender: 12,
448
+ maxToRenderPerBatch: 8,
449
+ windowSize: 5,
450
+ updateCellsBatchingPeriod: 50
451
451
  }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(EventsEmptyState, {
452
452
  isEnabled: isEnabled
453
453
  })]
@@ -462,6 +462,12 @@ function ZustandModal({
462
462
  onIndexChange: handleIndexChange
463
463
  }) : null;
464
464
  const footerHeight = selectedChange && activeChanges.length > 1 ? 68 : 0;
465
+
466
+ // The change lists own their scrolling so FlatList virtualization works
467
+ // (inside JsModal's ScrollView wrapper every row mounts — the Network
468
+ // tool measured 17 JS FPS / 133% CPU at max load from this exact
469
+ // pattern; see tool-bench batches 2026-07-06).
470
+ const listOwnsScroll = !showFilters && !(selectedChange && selectedChangeIndex !== null) && (selectedHistoryStore != null || activeTab === "events");
465
471
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.TickProvider, {
466
472
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.JsModal, {
467
473
  visible: visible,
@@ -476,6 +482,7 @@ function ZustandModal({
476
482
  enablePersistence: true,
477
483
  initialMode: "bottomSheet",
478
484
  enableGlitchEffects: true,
485
+ disableScrollWrapper: listOwnsScroll,
479
486
  styles: {},
480
487
  footer: footerNode,
481
488
  footerHeight: footerHeight,
@@ -3,7 +3,8 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.ZustandStateChangeItem = ZustandStateChangeItem;
6
+ exports.ZustandStateChangeItem = void 0;
7
+ var _react = require("react");
7
8
  var _reactNative = require("react-native");
8
9
  var _sharedUi = require("@buoy-gg/shared-ui");
9
10
  var _zustandStateStore = require("../utils/zustandStateStore");
@@ -88,7 +89,11 @@ function getPrimaryText(change) {
88
89
  }
89
90
  return change.partialPreview || "setState()";
90
91
  }
91
- function ZustandStateChangeItem({
92
+
93
+ // Memo justified by profiling (tool-bench 2026-07-06): unmemoized, every
94
+ // visible row re-rendered on each store emission. Leaf w/ stable props
95
+ // ({change, onPress} — onPress is a stable useCallback in the modal).
96
+ const ZustandStateChangeItem = exports.ZustandStateChangeItem = /*#__PURE__*/(0, _react.memo)(function ZustandStateChangeItem({
92
97
  change,
93
98
  onPress
94
99
  }) {
@@ -97,7 +102,6 @@ function ZustandStateChangeItem({
97
102
  const sublabel = getSublabel(change);
98
103
  const primaryText = getPrimaryText(change);
99
104
  const badgeText = getBadgeText(change);
100
- const relativeTime = (0, _sharedUi.useRelativeTime)(change.timestamp);
101
105
  let customBadge = undefined;
102
106
  if (change.isSlowUpdate) {
103
107
  customBadge = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
@@ -137,14 +141,16 @@ function ZustandStateChangeItem({
137
141
  statusLabel: statusLabel,
138
142
  statusSublabel: sublabel,
139
143
  primaryText: primaryText,
140
- bottomRightText: relativeTime,
144
+ bottomRightText: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.RelativeTime, {
145
+ timestamp: change.timestamp
146
+ }),
141
147
  customBadge: customBadge,
142
148
  badgeText: customBadge ? undefined : badgeText,
143
149
  badgeColor: statusColor,
144
150
  showChevron: true,
145
151
  onPress: () => onPress(change)
146
152
  });
147
- }
153
+ });
148
154
  const styles = _reactNative.StyleSheet.create({
149
155
  badgeContainer: {
150
156
  flexDirection: "row",
@@ -376,10 +376,10 @@ export function ZustandModal({
376
376
  contentContainerStyle: styles.listContent,
377
377
  showsVerticalScrollIndicator: true,
378
378
  removeClippedSubviews: true,
379
- initialNumToRender: 15,
380
- maxToRenderPerBatch: 10,
381
- windowSize: 10,
382
- scrollEnabled: false
379
+ initialNumToRender: 12,
380
+ maxToRenderPerBatch: 8,
381
+ windowSize: 5,
382
+ updateCellsBatchingPeriod: 50
383
383
  }) : /*#__PURE__*/_jsxs(View, {
384
384
  style: styles.emptyState,
385
385
  children: [/*#__PURE__*/_jsx(Box, {
@@ -440,10 +440,10 @@ export function ZustandModal({
440
440
  contentContainerStyle: styles.listContent,
441
441
  showsVerticalScrollIndicator: true,
442
442
  removeClippedSubviews: true,
443
- initialNumToRender: 15,
444
- maxToRenderPerBatch: 10,
445
- windowSize: 10,
446
- scrollEnabled: false
443
+ initialNumToRender: 12,
444
+ maxToRenderPerBatch: 8,
445
+ windowSize: 5,
446
+ updateCellsBatchingPeriod: 50
447
447
  }) : /*#__PURE__*/_jsx(EventsEmptyState, {
448
448
  isEnabled: isEnabled
449
449
  })]
@@ -458,6 +458,12 @@ export function ZustandModal({
458
458
  onIndexChange: handleIndexChange
459
459
  }) : null;
460
460
  const footerHeight = selectedChange && activeChanges.length > 1 ? 68 : 0;
461
+
462
+ // The change lists own their scrolling so FlatList virtualization works
463
+ // (inside JsModal's ScrollView wrapper every row mounts — the Network
464
+ // tool measured 17 JS FPS / 133% CPU at max load from this exact
465
+ // pattern; see tool-bench batches 2026-07-06).
466
+ const listOwnsScroll = !showFilters && !(selectedChange && selectedChangeIndex !== null) && (selectedHistoryStore != null || activeTab === "events");
461
467
  return /*#__PURE__*/_jsxs(TickProvider, {
462
468
  children: [/*#__PURE__*/_jsx(JsModal, {
463
469
  visible: visible,
@@ -472,6 +478,7 @@ export function ZustandModal({
472
478
  enablePersistence: true,
473
479
  initialMode: "bottomSheet",
474
480
  enableGlitchEffects: true,
481
+ disableScrollWrapper: listOwnsScroll,
475
482
  styles: {},
476
483
  footer: footerNode,
477
484
  footerHeight: footerHeight,
@@ -6,8 +6,9 @@
6
6
  * Mirrors ReduxActionItem.tsx - uses shared CompactRow for consistent styling
7
7
  */
8
8
 
9
+ import { memo } from "react";
9
10
  import { View, Text, StyleSheet } from "react-native";
10
- import { CompactRow, buoyColors, Zap, Clock, useRelativeTime } from "@buoy-gg/shared-ui";
11
+ import { CompactRow, buoyColors, Zap, Clock, RelativeTime } from "@buoy-gg/shared-ui";
11
12
  import { zustandStateStore } from "../utils/zustandStateStore";
12
13
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
14
  /**
@@ -84,7 +85,11 @@ function getPrimaryText(change) {
84
85
  }
85
86
  return change.partialPreview || "setState()";
86
87
  }
87
- export function ZustandStateChangeItem({
88
+
89
+ // Memo justified by profiling (tool-bench 2026-07-06): unmemoized, every
90
+ // visible row re-rendered on each store emission. Leaf w/ stable props
91
+ // ({change, onPress} — onPress is a stable useCallback in the modal).
92
+ export const ZustandStateChangeItem = /*#__PURE__*/memo(function ZustandStateChangeItem({
88
93
  change,
89
94
  onPress
90
95
  }) {
@@ -93,7 +98,6 @@ export function ZustandStateChangeItem({
93
98
  const sublabel = getSublabel(change);
94
99
  const primaryText = getPrimaryText(change);
95
100
  const badgeText = getBadgeText(change);
96
- const relativeTime = useRelativeTime(change.timestamp);
97
101
  let customBadge = undefined;
98
102
  if (change.isSlowUpdate) {
99
103
  customBadge = /*#__PURE__*/_jsxs(View, {
@@ -133,14 +137,16 @@ export function ZustandStateChangeItem({
133
137
  statusLabel: statusLabel,
134
138
  statusSublabel: sublabel,
135
139
  primaryText: primaryText,
136
- bottomRightText: relativeTime,
140
+ bottomRightText: /*#__PURE__*/_jsx(RelativeTime, {
141
+ timestamp: change.timestamp
142
+ }),
137
143
  customBadge: customBadge,
138
144
  badgeText: customBadge ? undefined : badgeText,
139
145
  badgeColor: statusColor,
140
146
  showChevron: true,
141
147
  onPress: () => onPress(change)
142
148
  });
143
- }
149
+ });
144
150
  const styles = StyleSheet.create({
145
151
  badgeContainer: {
146
152
  flexDirection: "row",
@@ -1 +1 @@
1
- {"version":3,"file":"ZustandModal.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandModal.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA2CH,OAAO,KAAK,EAAE,iBAAiB,EAAsB,MAAM,UAAU,CAAC;AAqBtE,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,OAAO,EACP,MAAM,EACN,UAAU,EACV,2BAAmC,GACpC,EAAE,iBAAiB,sCAuhBnB"}
1
+ {"version":3,"file":"ZustandModal.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandModal.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA2CH,OAAO,KAAK,EAAE,iBAAiB,EAAsB,MAAM,UAAU,CAAC;AAqBtE,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,OAAO,EACP,MAAM,EACN,UAAU,EACV,2BAAmC,GACpC,EAAE,iBAAiB,sCAiiBnB"}
@@ -8,6 +8,6 @@ interface ZustandStateChangeItemProps {
8
8
  change: ZustandStateChange;
9
9
  onPress: (change: ZustandStateChange) => void;
10
10
  }
11
- export declare function ZustandStateChangeItem({ change, onPress, }: ZustandStateChangeItemProps): import("react").JSX.Element;
11
+ export declare const ZustandStateChangeItem: import("react").NamedExoticComponent<ZustandStateChangeItemProps>;
12
12
  export {};
13
13
  //# sourceMappingURL=ZustandStateChangeItem.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ZustandStateChangeItem.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandStateChangeItem.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAuB,MAAM,UAAU,CAAC;AAGxE,UAAU,2BAA2B;IACnC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC/C;AAwFD,wBAAgB,sBAAsB,CAAC,EACrC,MAAM,EACN,OAAO,GACR,EAAE,2BAA2B,+BAgD7B"}
1
+ {"version":3,"file":"ZustandStateChangeItem.d.ts","sourceRoot":"","sources":["../../../../src/zustand/components/ZustandStateChangeItem.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAuB,MAAM,UAAU,CAAC;AAGxE,UAAU,2BAA2B;IACnC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC/C;AA2FD,eAAO,MAAM,sBAAsB,mEAkDjC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buoy-gg/zustand",
3
- "version": "5.0.0",
3
+ "version": "6.0.0",
4
4
  "description": "Zustand store DevTools for React Native",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -26,8 +26,8 @@
26
26
  ],
27
27
  "sideEffects": false,
28
28
  "dependencies": {
29
- "@buoy-gg/shared-ui": "5.0.0",
30
- "@buoy-gg/license": "5.0.0"
29
+ "@buoy-gg/shared-ui": "6.0.0",
30
+ "@buoy-gg/license": "6.0.0"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "react": "*",