@noya-app/noya-designsystem 0.1.70 → 0.1.72

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.
@@ -1,27 +1,20 @@
1
1
  "use client";
2
2
 
3
- import { Size } from "@noya-app/noya-geometry";
4
3
  import { range } from "@noya-app/noya-utils";
5
4
  import { forwardRefGeneric, memoGeneric } from "@noya-app/react-utils";
6
5
  import React, {
7
6
  CSSProperties,
8
7
  ForwardedRef,
9
8
  isValidElement,
10
- memo,
11
9
  ReactElement,
12
10
  ReactNode,
13
11
  useCallback,
14
- useContext,
15
- useImperativeHandle,
16
- useLayoutEffect,
17
12
  useMemo,
18
- useRef,
19
13
  } from "react";
20
- import { WindowScroller, WindowScrollerChildProps } from "react-virtualized";
21
- import { ListChildComponentProps, VariableSizeList } from "react-window";
22
14
  import { mergeConflictingClassNames } from "../../utils/classNames";
23
15
  import { IVirtualizedList } from "../IVirtualizedList";
24
16
  import { ScrollArea } from "../ScrollArea";
17
+ import { Virtualized } from "../Virtualized";
25
18
  import { SharedDragProps } from "../sorting/DragRegistration";
26
19
  import { Sortable } from "../sorting/Sortable";
27
20
  import {
@@ -36,7 +29,6 @@ import {
36
29
  ListViewContextValue,
37
30
  ListViewDraggingContext,
38
31
  ListViewDraggingContextValue,
39
- RenderItemContext,
40
32
  } from "./ListViewContexts";
41
33
  import {
42
34
  ListColorScheme,
@@ -56,129 +48,6 @@ export const SECTION_HEADER_LABEL_HEIGHT = 24;
56
48
  // use a taller height.
57
49
  export const TALL_ROW_HEIGHT = 50;
58
50
 
59
- const VirtualizedListRow = memo(function VirtualizedListRow({
60
- index,
61
- style,
62
- }: ListChildComponentProps) {
63
- const renderItem = useContext(RenderItemContext);
64
-
65
- return (
66
- <div key={index} style={style}>
67
- {renderItem(index)}
68
- </div>
69
- );
70
- });
71
-
72
- /* ----------------------------------------------------------------------------
73
- * VirtualizedList
74
- * ------------------------------------------------------------------------- */
75
-
76
- interface VirtualizedListProps<T> {
77
- size: Size;
78
- scrollElement: HTMLDivElement;
79
- items: T[];
80
- getItemHeight: (index: number) => number;
81
- keyExtractor: (index: number) => string;
82
- renderItem: (index: number) => ReactNode;
83
- }
84
-
85
- const VirtualizedListInner = forwardRefGeneric(function VirtualizedListInner<T>(
86
- {
87
- size,
88
- scrollElement,
89
- items,
90
- getItemHeight,
91
- keyExtractor,
92
- renderItem,
93
- }: VirtualizedListProps<T>,
94
- ref: ForwardedRef<IVirtualizedList>
95
- ) {
96
- const listRef = useRef<VariableSizeList<T> | null>(null);
97
-
98
- useImperativeHandle(ref, () => ({
99
- scrollToIndex(index) {
100
- listRef.current?.scrollToItem(index);
101
- },
102
- }));
103
-
104
- useLayoutEffect(() => {
105
- listRef.current?.resetAfterIndex(0);
106
- }, [
107
- // When items or the height resolver change, re-render the virtualized list
108
- // since VariableSizeList caches sizes per index.
109
- items,
110
- getItemHeight,
111
- ]);
112
-
113
- // Internally, react-virtualized updates these properties. We always want
114
- // to use our custom scroll element, so we override them. It may update
115
- // overflowX/Y individually in addition to `overflow`, so we include all 3.
116
- const listStyle = useMemo(
117
- (): CSSProperties => ({
118
- overflowX: "initial",
119
- overflowY: "initial",
120
- overflow: "initial",
121
- }),
122
- []
123
- );
124
-
125
- return (
126
- <RenderItemContext.Provider value={renderItem}>
127
- <WindowScroller
128
- scrollElement={scrollElement}
129
- style={useMemo(() => ({ flex: "1 1 auto" }), [])}
130
- >
131
- {useCallback(
132
- ({
133
- registerChild,
134
- onChildScroll,
135
- scrollTop,
136
- }: WindowScrollerChildProps & {
137
- // Added when noya-designsystem moved to a separate package.
138
- // I think this is a hack to get around the fact that react-virtualized
139
- // doesn't update on scroll unless we force it to by changing ref.
140
- // Either we're not using this the intended way or the types are wrong.
141
- registerChild: (element: any) => void;
142
- }) => (
143
- <div ref={registerChild}>
144
- <VariableSizeList<T>
145
- ref={listRef}
146
- // The list won't update on scroll unless we force it to by changing key
147
- key={scrollTop}
148
- style={listStyle}
149
- itemKey={keyExtractor}
150
- onScroll={({ scrollOffset }: { scrollOffset: number }) => {
151
- onChildScroll({ scrollTop: scrollOffset });
152
- }}
153
- initialScrollOffset={scrollTop}
154
- width={size.width}
155
- height={size.height}
156
- itemCount={items.length}
157
- itemSize={getItemHeight}
158
- estimatedItemSize={ROW_HEIGHT}
159
- >
160
- {VirtualizedListRow as any}
161
- </VariableSizeList>
162
- </div>
163
- ),
164
- [
165
- listStyle,
166
- keyExtractor,
167
- size.width,
168
- size.height,
169
- items.length,
170
- getItemHeight,
171
- ]
172
- )}
173
- </WindowScroller>
174
- </RenderItemContext.Provider>
175
- );
176
- });
177
-
178
- const VirtualizedList = memo(
179
- VirtualizedListInner
180
- ) as typeof VirtualizedListInner;
181
-
182
51
  /* ----------------------------------------------------------------------------
183
52
  * Root
184
53
  * ------------------------------------------------------------------------- */
@@ -198,7 +67,7 @@ export type ListViewRootProps<T> = {
198
67
  * Additionally, the key extracted with `keyExtractor` must match the ListItem.Row `id`.
199
68
  */
200
69
  sortable?: boolean;
201
- virtualized?: Size;
70
+ virtualized?: number;
202
71
 
203
72
  id?: string;
204
73
  className?: string;
@@ -432,9 +301,8 @@ export const ListViewRoot = memoGeneric(
432
301
  children
433
302
  );
434
303
 
435
- const withScrollable = (
436
- children: (scrollElementRef: HTMLDivElement | null) => ReactNode
437
- ) => (scrollable ? <ScrollArea>{children}</ScrollArea> : children(null));
304
+ const withScrollable = (children: ReactNode) =>
305
+ scrollable ? <ScrollArea>{children}</ScrollArea> : children;
438
306
 
439
307
  const getItemHeight = useCallback(
440
308
  (index: number) => {
@@ -528,23 +396,21 @@ export const ListViewRoot = memoGeneric(
528
396
  >
529
397
  {data.length === 0 && renderEmptyState
530
398
  ? renderEmptyState()
531
- : withScrollable((scrollElementRef: HTMLDivElement | null) =>
532
- withSortable(
533
- virtualized ? (
534
- <VirtualizedList<T>
535
- ref={forwardedRef}
536
- scrollElement={scrollElementRef!}
537
- items={data}
538
- size={virtualized}
539
- getItemHeight={getItemHeight}
540
- keyExtractor={getKey}
541
- renderItem={renderWrappedChild}
542
- />
543
- ) : (
544
- range(0, data.length).map(renderWrappedChild)
545
- )
399
+ : virtualized != null
400
+ ? withSortable(
401
+ <Virtualized
402
+ ref={forwardedRef}
403
+ height={virtualized}
404
+ itemCount={data.length}
405
+ getItemHeight={getItemHeight}
406
+ renderItem={renderWrappedChild}
407
+ itemKey={getKey}
408
+ useScrollArea={scrollable}
409
+ />
546
410
  )
547
- )}
411
+ : withScrollable(
412
+ withSortable(range(0, data.length).map(renderWrappedChild))
413
+ )}
548
414
  </div>
549
415
  </ListViewDraggingContext.Provider>
550
416
  </ListViewContext.Provider>
package/src/index.tsx CHANGED
@@ -83,7 +83,13 @@ export * from "./components/TextArea";
83
83
  export * from "./components/Toast";
84
84
  export * from "./components/Tooltip";
85
85
  export * from "./components/TreeView";
86
+ export * from "./components/UserPicker";
86
87
  export * from "./components/UserPointer";
88
+ export {
89
+ Virtualized,
90
+ type VirtualizedProps,
91
+ type VirtualizedRenderItem,
92
+ } from "./components/Virtualized";
87
93
  export * from "./components/workspace/types";
88
94
  export * from "./components/workspace/WorkspaceLayout";
89
95
  export * from "./components/workspace/WorkspaceSideContext";