@legendapp/list 1.0.0-beta.14 → 1.0.0-beta.16

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/animated.d.mts CHANGED
@@ -16,6 +16,7 @@ declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<re
16
16
  alignItemsAtEnd?: boolean;
17
17
  maintainVisibleContentPosition?: boolean;
18
18
  numColumns?: number;
19
+ columnWrapperStyle?: _legendapp_list.ColumnWrapperStyle;
19
20
  refScrollView?: React.Ref<react_native.ScrollView>;
20
21
  waitForInitialLayout?: boolean;
21
22
  estimatedItemSize?: number;
package/animated.d.ts CHANGED
@@ -16,6 +16,7 @@ declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<re
16
16
  alignItemsAtEnd?: boolean;
17
17
  maintainVisibleContentPosition?: boolean;
18
18
  numColumns?: number;
19
+ columnWrapperStyle?: _legendapp_list.ColumnWrapperStyle;
19
20
  refScrollView?: React.Ref<react_native.ScrollView>;
20
21
  waitForInitialLayout?: boolean;
21
22
  estimatedItemSize?: number;
package/index.d.mts CHANGED
@@ -31,6 +31,7 @@ type LegendListPropsBase<ItemT, TScrollView extends ComponentProps<typeof Scroll
31
31
  alignItemsAtEnd?: boolean;
32
32
  maintainVisibleContentPosition?: boolean;
33
33
  numColumns?: number;
34
+ columnWrapperStyle?: ColumnWrapperStyle;
34
35
  refScrollView?: React.Ref<ScrollView>;
35
36
  waitForInitialLayout?: boolean;
36
37
  estimatedItemSize?: number;
@@ -66,6 +67,11 @@ type LegendListPropsBase<ItemT, TScrollView extends ComponentProps<typeof Scroll
66
67
  renderScrollComponent?: (props: ScrollViewProps) => React.ReactElement<ScrollViewProps>;
67
68
  extraData?: any;
68
69
  };
70
+ interface ColumnWrapperStyle {
71
+ rowGap?: number;
72
+ gap?: number;
73
+ columnGap?: number;
74
+ }
69
75
  type AnchoredPosition = {
70
76
  type: "top" | "bottom";
71
77
  relativeCoordinate: number;
@@ -251,6 +257,7 @@ declare const LegendList: <T>(props: Omit<react_native.ScrollViewProps, "content
251
257
  alignItemsAtEnd?: boolean;
252
258
  maintainVisibleContentPosition?: boolean;
253
259
  numColumns?: number;
260
+ columnWrapperStyle?: ColumnWrapperStyle;
254
261
  refScrollView?: React$1.Ref<ScrollView>;
255
262
  waitForInitialLayout?: boolean;
256
263
  estimatedItemSize?: number;
@@ -288,4 +295,4 @@ declare function useViewabilityAmount(callback: ViewabilityAmountCallback): void
288
295
  declare function useRecyclingEffect(effect: (info: LegendListRecyclingState<unknown>) => void | (() => void)): void;
289
296
  declare function useRecyclingState(valueOrFun: ((info: LegendListRecyclingState<unknown>) => any) | any): [any, React$1.Dispatch<any>];
290
297
 
291
- export { type AnchoredPosition, type InternalState, LegendList, type LegendListProps, type LegendListPropsBase, type LegendListRecyclingState, type LegendListRef, type LegendListRenderItemProps, type OnViewableItemsChanged, type TypedForwardRef, type ViewAmountToken, type ViewToken, type ViewabilityAmountCallback, type ViewabilityCallback, type ViewabilityConfig, type ViewabilityConfigCallbackPair, type ViewabilityConfigCallbackPairs, type ViewableRange, typedForwardRef, useRecyclingEffect, useRecyclingState, useViewability, useViewabilityAmount };
298
+ export { type AnchoredPosition, type ColumnWrapperStyle, type InternalState, LegendList, type LegendListProps, type LegendListPropsBase, type LegendListRecyclingState, type LegendListRef, type LegendListRenderItemProps, type OnViewableItemsChanged, type TypedForwardRef, type ViewAmountToken, type ViewToken, type ViewabilityAmountCallback, type ViewabilityCallback, type ViewabilityConfig, type ViewabilityConfigCallbackPair, type ViewabilityConfigCallbackPairs, type ViewableRange, typedForwardRef, useRecyclingEffect, useRecyclingState, useViewability, useViewabilityAmount };
package/index.d.ts CHANGED
@@ -31,6 +31,7 @@ type LegendListPropsBase<ItemT, TScrollView extends ComponentProps<typeof Scroll
31
31
  alignItemsAtEnd?: boolean;
32
32
  maintainVisibleContentPosition?: boolean;
33
33
  numColumns?: number;
34
+ columnWrapperStyle?: ColumnWrapperStyle;
34
35
  refScrollView?: React.Ref<ScrollView>;
35
36
  waitForInitialLayout?: boolean;
36
37
  estimatedItemSize?: number;
@@ -66,6 +67,11 @@ type LegendListPropsBase<ItemT, TScrollView extends ComponentProps<typeof Scroll
66
67
  renderScrollComponent?: (props: ScrollViewProps) => React.ReactElement<ScrollViewProps>;
67
68
  extraData?: any;
68
69
  };
70
+ interface ColumnWrapperStyle {
71
+ rowGap?: number;
72
+ gap?: number;
73
+ columnGap?: number;
74
+ }
69
75
  type AnchoredPosition = {
70
76
  type: "top" | "bottom";
71
77
  relativeCoordinate: number;
@@ -251,6 +257,7 @@ declare const LegendList: <T>(props: Omit<react_native.ScrollViewProps, "content
251
257
  alignItemsAtEnd?: boolean;
252
258
  maintainVisibleContentPosition?: boolean;
253
259
  numColumns?: number;
260
+ columnWrapperStyle?: ColumnWrapperStyle;
254
261
  refScrollView?: React$1.Ref<ScrollView>;
255
262
  waitForInitialLayout?: boolean;
256
263
  estimatedItemSize?: number;
@@ -288,4 +295,4 @@ declare function useViewabilityAmount(callback: ViewabilityAmountCallback): void
288
295
  declare function useRecyclingEffect(effect: (info: LegendListRecyclingState<unknown>) => void | (() => void)): void;
289
296
  declare function useRecyclingState(valueOrFun: ((info: LegendListRecyclingState<unknown>) => any) | any): [any, React$1.Dispatch<any>];
290
297
 
291
- export { type AnchoredPosition, type InternalState, LegendList, type LegendListProps, type LegendListPropsBase, type LegendListRecyclingState, type LegendListRef, type LegendListRenderItemProps, type OnViewableItemsChanged, type TypedForwardRef, type ViewAmountToken, type ViewToken, type ViewabilityAmountCallback, type ViewabilityCallback, type ViewabilityConfig, type ViewabilityConfigCallbackPair, type ViewabilityConfigCallbackPairs, type ViewableRange, typedForwardRef, useRecyclingEffect, useRecyclingState, useViewability, useViewabilityAmount };
298
+ export { type AnchoredPosition, type ColumnWrapperStyle, type InternalState, LegendList, type LegendListProps, type LegendListPropsBase, type LegendListRecyclingState, type LegendListRef, type LegendListRenderItemProps, type OnViewableItemsChanged, type TypedForwardRef, type ViewAmountToken, type ViewToken, type ViewabilityAmountCallback, type ViewabilityCallback, type ViewabilityConfig, type ViewabilityConfigCallbackPair, type ViewabilityConfigCallbackPairs, type ViewableRange, typedForwardRef, useRecyclingEffect, useRecyclingState, useViewability, useViewabilityAmount };
package/index.js CHANGED
@@ -32,7 +32,8 @@ function StateProvider({ children }) {
32
32
  mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
33
33
  mapViewabilityValues: /* @__PURE__ */ new Map(),
34
34
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
35
- mapViewabilityAmountValues: /* @__PURE__ */ new Map()
35
+ mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
36
+ columnWrapperStyle: void 0
36
37
  }));
37
38
  return /* @__PURE__ */ React6__namespace.createElement(ContextState.Provider, { value }, children);
38
39
  }
@@ -168,7 +169,7 @@ var DebugView = React6.memo(function DebugView2({ state }) {
168
169
  useInterval(() => {
169
170
  forceUpdate();
170
171
  }, 100);
171
- return /* @__PURE__ */ React.createElement(
172
+ return /* @__PURE__ */ React6__namespace.createElement(
172
173
  reactNative.View,
173
174
  {
174
175
  style: {
@@ -181,8 +182,8 @@ var DebugView = React6.memo(function DebugView2({ state }) {
181
182
  backgroundColor: "#FFFFFFCC"
182
183
  }
183
184
  },
184
- /* @__PURE__ */ React.createElement(reactNative.Text, null, "PaddingTop: ", paddingTop),
185
- /* @__PURE__ */ React.createElement(reactNative.Text, null, "At end: ", String(state.isAtBottom))
185
+ /* @__PURE__ */ React6__namespace.createElement(reactNative.Text, null, "PaddingTop: ", paddingTop),
186
+ /* @__PURE__ */ React6__namespace.createElement(reactNative.Text, null, "At end: ", String(state.isAtBottom))
186
187
  );
187
188
  });
188
189
  function useInterval(callback, delay) {
@@ -217,12 +218,24 @@ var Container = ({
217
218
  updateItemSize,
218
219
  ItemSeparatorComponent
219
220
  }) => {
221
+ const ctx = useStateContext();
222
+ const columnWrapperStyle = ctx.columnWrapperStyle;
220
223
  const maintainVisibleContentPosition = use$("maintainVisibleContentPosition");
221
224
  const position = use$(`containerPosition${id}`) || ANCHORED_POSITION_OUT_OF_VIEW;
222
225
  const column = use$(`containerColumn${id}`) || 0;
223
226
  const numColumns = use$("numColumns");
224
227
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
225
228
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
229
+ let verticalPaddingStyles;
230
+ if (columnWrapperStyle && !horizontal && numColumns > 1) {
231
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
232
+ verticalPaddingStyles = {
233
+ paddingVertical: rowGap || gap || void 0,
234
+ // Apply horizontal padding based on column position (first, middle, or last)
235
+ paddingLeft: column > 1 ? (columnGap || gap || 0) / 2 : void 0,
236
+ paddingRight: column < numColumns ? (columnGap || gap || 0) / 2 : void 0
237
+ };
238
+ }
226
239
  const style = horizontal ? {
227
240
  flexDirection: ItemSeparatorComponent ? "row" : void 0,
228
241
  position: "absolute",
@@ -235,7 +248,8 @@ var Container = ({
235
248
  left: otherAxisPos,
236
249
  right: numColumns > 1 ? null : 0,
237
250
  width: otherAxisSize,
238
- top: position.relativeCoordinate
251
+ top: position.relativeCoordinate,
252
+ ...verticalPaddingStyles || {}
239
253
  };
240
254
  const lastItemKey = use$("lastItemKey");
241
255
  const itemKey = use$(`containerItemKey${id}`);
@@ -248,9 +262,17 @@ var Container = ({
248
262
  const { index, renderedItem } = renderedItemInfo || {};
249
263
  const onLayout = (event) => {
250
264
  if (itemKey !== void 0) {
251
- const size = Math.floor(event.nativeEvent.layout[horizontal ? "width" : "height"] * 8) / 8;
265
+ const layout = event.nativeEvent.layout;
266
+ const size = Math.floor(layout[horizontal ? "width" : "height"] * 8) / 8;
252
267
  if (size === 0) {
253
- console.log("[WARN] Container 0 height reported, possible bug in LegendList", id, itemKey);
268
+ if (layout.y !== POSITION_OUT_OF_VIEW && layout.y !== POSITION_OUT_OF_VIEW) {
269
+ console.log(
270
+ "[WARN] Container 0 height reported, possible bug in LegendList",
271
+ id,
272
+ itemKey,
273
+ event.nativeEvent
274
+ );
275
+ }
254
276
  return;
255
277
  }
256
278
  updateItemSize(id, itemKey, size);
@@ -286,9 +308,9 @@ var Container = ({
286
308
  }
287
309
  return /* @__PURE__ */ React6__namespace.default.createElement(LeanView, { style, onLayout, ref }, contentFragment);
288
310
  };
289
- var useAnimatedValue = reactNative.useAnimatedValue || ((initialValue) => {
311
+ var useAnimatedValue = (initialValue) => {
290
312
  return React6.useRef(new reactNative.Animated.Value(initialValue)).current;
291
- });
313
+ };
292
314
 
293
315
  // src/useValue$.ts
294
316
  function useValue$(key, getValue, useMicrotask) {
@@ -718,6 +740,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
718
740
  onScroll: onScrollProp,
719
741
  onMomentumScrollEnd,
720
742
  numColumns: numColumnsProp = 1,
743
+ columnWrapperStyle,
721
744
  keyExtractor: keyExtractorProp,
722
745
  renderItem,
723
746
  estimatedItemSize,
@@ -739,6 +762,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
739
762
  callbacks.current.onStartReached = rest.onStartReached;
740
763
  callbacks.current.onEndReached = rest.onEndReached;
741
764
  const ctx = useStateContext();
765
+ ctx.columnWrapperStyle = columnWrapperStyle;
742
766
  const refScroller = React6.useRef(null);
743
767
  const combinedRef = useCombinedRef(refScroller, refScrollView);
744
768
  const scrollBuffer = drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE;
@@ -1238,9 +1262,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1238
1262
  if (!refState.current) {
1239
1263
  return;
1240
1264
  }
1241
- const { scrollLength, scroll, totalSize } = refState.current;
1242
- if (totalSize > 0) {
1243
- const distanceFromEnd = totalSize - scroll - scrollLength + (peek$(ctx, "paddingTop") || 0);
1265
+ const { scrollLength, scroll, totalSize, hasScrolled } = refState.current;
1266
+ if (totalSize > 0 && hasScrolled) {
1267
+ const distanceFromEnd = Math.abs(
1268
+ totalSize - scroll - scrollLength + (peek$(ctx, "paddingTop") || 0)
1269
+ );
1244
1270
  if (refState.current) {
1245
1271
  refState.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1246
1272
  }
@@ -1395,12 +1421,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1395
1421
  refState.current.positions.clear();
1396
1422
  }
1397
1423
  refState.current.data = dataProp;
1398
- const indexByKey = /* @__PURE__ */ new Map();
1399
- for (let i = 0; i < dataProp.length; i++) {
1400
- const key = getId(i);
1401
- indexByKey.set(key, i);
1402
- }
1403
- refState.current.indexByKey = indexByKey;
1404
1424
  calcTotalSizesAndPositions({ forgetPositions: false });
1405
1425
  }
1406
1426
  React6.useEffect(() => {
package/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as React6 from 'react';
2
2
  import React6__default, { createContext, memo, useReducer, useEffect, useMemo, useRef, useCallback, useImperativeHandle, useSyncExternalStore, useContext, useState, forwardRef, useLayoutEffect } from 'react';
3
- import { View, Text, Platform, Animated, ScrollView, Dimensions, StyleSheet, useAnimatedValue as useAnimatedValue$1 } from 'react-native';
3
+ import { View, Text, Platform, Animated, ScrollView, Dimensions, StyleSheet } from 'react-native';
4
4
 
5
5
  // src/LegendList.tsx
6
6
  var ContextState = React6.createContext(null);
@@ -11,7 +11,8 @@ function StateProvider({ children }) {
11
11
  mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
12
12
  mapViewabilityValues: /* @__PURE__ */ new Map(),
13
13
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
14
- mapViewabilityAmountValues: /* @__PURE__ */ new Map()
14
+ mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
15
+ columnWrapperStyle: void 0
15
16
  }));
16
17
  return /* @__PURE__ */ React6.createElement(ContextState.Provider, { value }, children);
17
18
  }
@@ -147,7 +148,7 @@ var DebugView = memo(function DebugView2({ state }) {
147
148
  useInterval(() => {
148
149
  forceUpdate();
149
150
  }, 100);
150
- return /* @__PURE__ */ React.createElement(
151
+ return /* @__PURE__ */ React6.createElement(
151
152
  View,
152
153
  {
153
154
  style: {
@@ -160,8 +161,8 @@ var DebugView = memo(function DebugView2({ state }) {
160
161
  backgroundColor: "#FFFFFFCC"
161
162
  }
162
163
  },
163
- /* @__PURE__ */ React.createElement(Text, null, "PaddingTop: ", paddingTop),
164
- /* @__PURE__ */ React.createElement(Text, null, "At end: ", String(state.isAtBottom))
164
+ /* @__PURE__ */ React6.createElement(Text, null, "PaddingTop: ", paddingTop),
165
+ /* @__PURE__ */ React6.createElement(Text, null, "At end: ", String(state.isAtBottom))
165
166
  );
166
167
  });
167
168
  function useInterval(callback, delay) {
@@ -196,12 +197,24 @@ var Container = ({
196
197
  updateItemSize,
197
198
  ItemSeparatorComponent
198
199
  }) => {
200
+ const ctx = useStateContext();
201
+ const columnWrapperStyle = ctx.columnWrapperStyle;
199
202
  const maintainVisibleContentPosition = use$("maintainVisibleContentPosition");
200
203
  const position = use$(`containerPosition${id}`) || ANCHORED_POSITION_OUT_OF_VIEW;
201
204
  const column = use$(`containerColumn${id}`) || 0;
202
205
  const numColumns = use$("numColumns");
203
206
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
204
207
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
208
+ let verticalPaddingStyles;
209
+ if (columnWrapperStyle && !horizontal && numColumns > 1) {
210
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
211
+ verticalPaddingStyles = {
212
+ paddingVertical: rowGap || gap || void 0,
213
+ // Apply horizontal padding based on column position (first, middle, or last)
214
+ paddingLeft: column > 1 ? (columnGap || gap || 0) / 2 : void 0,
215
+ paddingRight: column < numColumns ? (columnGap || gap || 0) / 2 : void 0
216
+ };
217
+ }
205
218
  const style = horizontal ? {
206
219
  flexDirection: ItemSeparatorComponent ? "row" : void 0,
207
220
  position: "absolute",
@@ -214,7 +227,8 @@ var Container = ({
214
227
  left: otherAxisPos,
215
228
  right: numColumns > 1 ? null : 0,
216
229
  width: otherAxisSize,
217
- top: position.relativeCoordinate
230
+ top: position.relativeCoordinate,
231
+ ...verticalPaddingStyles || {}
218
232
  };
219
233
  const lastItemKey = use$("lastItemKey");
220
234
  const itemKey = use$(`containerItemKey${id}`);
@@ -227,9 +241,17 @@ var Container = ({
227
241
  const { index, renderedItem } = renderedItemInfo || {};
228
242
  const onLayout = (event) => {
229
243
  if (itemKey !== void 0) {
230
- const size = Math.floor(event.nativeEvent.layout[horizontal ? "width" : "height"] * 8) / 8;
244
+ const layout = event.nativeEvent.layout;
245
+ const size = Math.floor(layout[horizontal ? "width" : "height"] * 8) / 8;
231
246
  if (size === 0) {
232
- console.log("[WARN] Container 0 height reported, possible bug in LegendList", id, itemKey);
247
+ if (layout.y !== POSITION_OUT_OF_VIEW && layout.y !== POSITION_OUT_OF_VIEW) {
248
+ console.log(
249
+ "[WARN] Container 0 height reported, possible bug in LegendList",
250
+ id,
251
+ itemKey,
252
+ event.nativeEvent
253
+ );
254
+ }
233
255
  return;
234
256
  }
235
257
  updateItemSize(id, itemKey, size);
@@ -265,9 +287,9 @@ var Container = ({
265
287
  }
266
288
  return /* @__PURE__ */ React6__default.createElement(LeanView, { style, onLayout, ref }, contentFragment);
267
289
  };
268
- var useAnimatedValue = useAnimatedValue$1 || ((initialValue) => {
290
+ var useAnimatedValue = (initialValue) => {
269
291
  return useRef(new Animated.Value(initialValue)).current;
270
- });
292
+ };
271
293
 
272
294
  // src/useValue$.ts
273
295
  function useValue$(key, getValue, useMicrotask) {
@@ -697,6 +719,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
697
719
  onScroll: onScrollProp,
698
720
  onMomentumScrollEnd,
699
721
  numColumns: numColumnsProp = 1,
722
+ columnWrapperStyle,
700
723
  keyExtractor: keyExtractorProp,
701
724
  renderItem,
702
725
  estimatedItemSize,
@@ -718,6 +741,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
718
741
  callbacks.current.onStartReached = rest.onStartReached;
719
742
  callbacks.current.onEndReached = rest.onEndReached;
720
743
  const ctx = useStateContext();
744
+ ctx.columnWrapperStyle = columnWrapperStyle;
721
745
  const refScroller = useRef(null);
722
746
  const combinedRef = useCombinedRef(refScroller, refScrollView);
723
747
  const scrollBuffer = drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE;
@@ -1217,9 +1241,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1217
1241
  if (!refState.current) {
1218
1242
  return;
1219
1243
  }
1220
- const { scrollLength, scroll, totalSize } = refState.current;
1221
- if (totalSize > 0) {
1222
- const distanceFromEnd = totalSize - scroll - scrollLength + (peek$(ctx, "paddingTop") || 0);
1244
+ const { scrollLength, scroll, totalSize, hasScrolled } = refState.current;
1245
+ if (totalSize > 0 && hasScrolled) {
1246
+ const distanceFromEnd = Math.abs(
1247
+ totalSize - scroll - scrollLength + (peek$(ctx, "paddingTop") || 0)
1248
+ );
1223
1249
  if (refState.current) {
1224
1250
  refState.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1225
1251
  }
@@ -1374,12 +1400,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1374
1400
  refState.current.positions.clear();
1375
1401
  }
1376
1402
  refState.current.data = dataProp;
1377
- const indexByKey = /* @__PURE__ */ new Map();
1378
- for (let i = 0; i < dataProp.length; i++) {
1379
- const key = getId(i);
1380
- indexByKey.set(key, i);
1381
- }
1382
- refState.current.indexByKey = indexByKey;
1383
1403
  calcTotalSizesAndPositions({ forgetPositions: false });
1384
1404
  }
1385
1405
  useEffect(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "1.0.0-beta.14",
3
+ "version": "1.0.0-beta.16",
4
4
  "description": "Legend List aims to be a drop-in replacement for FlatList with much better performance and supporting dynamically sized items.",
5
5
  "sideEffects": false,
6
6
  "private": false,