@react-fabric/data 1.0.0-beta.5 → 1.0.0-beta.52

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 (109) hide show
  1. package/{src/histogram/Histogram.module.css → css/_histogram.css} +16 -13
  2. package/css/styles.css +24 -0
  3. package/dist/cjs/checklist/CheckList.js +48 -16
  4. package/dist/cjs/histogram/Histogram.js +48 -10
  5. package/dist/cjs/hooks/useFilteredList.js +20 -0
  6. package/dist/cjs/hooks/usePagination.js +27 -4
  7. package/dist/cjs/hooks/useSelectableList.js +29 -0
  8. package/dist/cjs/i18n/ar.json.js +8 -1
  9. package/dist/cjs/i18n/en.json.js +8 -1
  10. package/dist/cjs/json/JsonViewer.js +67 -27
  11. package/dist/cjs/pagination/Pagination.js +10 -0
  12. package/dist/cjs/table/AddColumn.js +1 -1
  13. package/dist/cjs/table/BodyCell.js +38 -5
  14. package/dist/cjs/table/BodyRow.js +107 -0
  15. package/dist/cjs/table/CheckboxCell.js +1 -1
  16. package/dist/cjs/table/ColumnFilters.js +97 -0
  17. package/dist/cjs/table/HeaderCell.js +70 -37
  18. package/dist/cjs/table/Table.js +113 -71
  19. package/dist/cjs/table/types.js +29 -0
  20. package/dist/cjs/table/useResizer.js +4 -4
  21. package/dist/cjs/table/useVirtualTable.js +122 -18
  22. package/dist/cjs/tree/TreeNode.js +45 -25
  23. package/dist/cjs/tree/TreePanel.js +28 -10
  24. package/dist/cjs/tree/useTree.js +97 -15
  25. package/dist/cjs/tree/utils.js +20 -5
  26. package/dist/cjs/virtual/Gallery.js +84 -35
  27. package/dist/cjs/virtual/List.js +82 -32
  28. package/dist/esm/checklist/CheckList.js +50 -18
  29. package/dist/esm/histogram/Histogram.js +49 -11
  30. package/dist/esm/hooks/useFilteredList.js +20 -0
  31. package/dist/esm/hooks/usePagination.js +27 -4
  32. package/dist/esm/hooks/useSelectableList.js +29 -0
  33. package/dist/esm/i18n/ar.json.js +8 -2
  34. package/dist/esm/i18n/en.json.js +8 -2
  35. package/dist/esm/json/JsonViewer.js +68 -28
  36. package/dist/esm/pagination/Pagination.js +10 -0
  37. package/dist/esm/table/AddColumn.js +1 -1
  38. package/dist/esm/table/BodyCell.js +38 -5
  39. package/dist/esm/table/BodyRow.js +107 -0
  40. package/dist/esm/table/CheckboxCell.js +1 -1
  41. package/dist/esm/table/ColumnFilters.js +97 -0
  42. package/dist/esm/table/HeaderCell.js +71 -38
  43. package/dist/esm/table/Table.js +115 -73
  44. package/dist/esm/table/types.js +29 -0
  45. package/dist/esm/table/useResizer.js +4 -4
  46. package/dist/esm/table/useVirtualTable.js +124 -20
  47. package/dist/esm/tree/TreeNode.js +47 -27
  48. package/dist/esm/tree/TreePanel.js +28 -10
  49. package/dist/esm/tree/useTree.js +99 -17
  50. package/dist/esm/tree/utils.js +20 -5
  51. package/dist/esm/virtual/Gallery.js +84 -35
  52. package/dist/esm/virtual/List.js +82 -32
  53. package/dist/types/checklist/CheckList.d.ts +24 -2
  54. package/dist/types/histogram/Histogram.d.ts +31 -4
  55. package/dist/types/hooks/useFilteredList.d.ts +20 -2
  56. package/dist/types/hooks/usePagination.d.ts +19 -0
  57. package/dist/types/hooks/useSelectableList.d.ts +29 -0
  58. package/dist/types/index.d.ts +1 -1
  59. package/dist/types/json/JsonViewer.d.ts +27 -2
  60. package/dist/types/pagination/Pagination.d.ts +10 -1
  61. package/dist/types/table/AddColumn.d.ts +2 -2
  62. package/dist/types/table/BodyCell.d.ts +4 -3
  63. package/dist/types/table/BodyRow.d.ts +20 -0
  64. package/dist/types/table/ColumnFilters.d.ts +9 -0
  65. package/dist/types/table/EmptyCell.d.ts +2 -2
  66. package/dist/types/table/HeaderCell.d.ts +2 -2
  67. package/dist/types/table/Table.d.ts +14 -1
  68. package/dist/types/table/types.d.ts +48 -7
  69. package/dist/types/table/useTableColumns.d.ts +6 -6
  70. package/dist/types/table/useVirtualTable.d.ts +23 -8
  71. package/dist/types/tree/TreeNode.d.ts +1 -1
  72. package/dist/types/tree/TreePanel.d.ts +42 -1
  73. package/dist/types/tree/types.d.ts +25 -5
  74. package/dist/types/tree/useTree.d.ts +3 -10
  75. package/dist/types/tree/utils.d.ts +4 -1
  76. package/dist/types/virtual/Gallery.d.ts +44 -4
  77. package/dist/types/virtual/List.d.ts +44 -4
  78. package/package.json +13 -10
  79. package/src/checklist/CheckList.tsx +103 -77
  80. package/src/histogram/Histogram.tsx +45 -11
  81. package/src/hooks/useFilteredList.tsx +19 -0
  82. package/src/hooks/usePagination.tsx +32 -7
  83. package/src/hooks/useSelectableList.ts +29 -0
  84. package/src/i18n/ar.json +5 -0
  85. package/src/i18n/en.json +5 -0
  86. package/src/index.ts +1 -1
  87. package/src/json/JsonViewer.tsx +71 -35
  88. package/src/pagination/Pagination.tsx +10 -0
  89. package/src/table/AddColumn.tsx +3 -3
  90. package/src/table/BodyCell.tsx +34 -5
  91. package/src/table/BodyRow.tsx +143 -0
  92. package/src/table/CheckboxCell.tsx +1 -1
  93. package/src/table/ColumnFilters.tsx +105 -0
  94. package/src/table/EmptyCell.tsx +2 -2
  95. package/src/table/HeaderCell.tsx +72 -14
  96. package/src/table/Table.tsx +177 -77
  97. package/src/table/types.ts +52 -6
  98. package/src/table/useResizer.ts +5 -3
  99. package/src/table/useTableColumns.ts +7 -7
  100. package/src/table/useVirtualTable.ts +146 -24
  101. package/src/tree/TreeNode.tsx +98 -56
  102. package/src/tree/TreePanel.tsx +64 -3
  103. package/src/tree/types.ts +32 -4
  104. package/src/tree/useTree.ts +109 -26
  105. package/src/tree/utils.ts +23 -8
  106. package/src/virtual/Gallery.tsx +96 -42
  107. package/src/virtual/List.tsx +82 -33
  108. package/dist/cjs/histogram/Histogram.module.css +0 -1
  109. package/dist/esm/histogram/Histogram.module.css +0 -1
@@ -29,6 +29,7 @@
29
29
  */
30
30
 
31
31
  import { Skeleton, useDebounce } from "@react-fabric/core";
32
+ import { type TestProps } from "@react-fabric/core/dist/types/types";
32
33
  import { debounce } from "@react-fabric/utilities";
33
34
  import { useVirtualizer } from "@tanstack/react-virtual";
34
35
  import classNames from "classnames";
@@ -54,9 +55,9 @@ export interface VirtualListRef {
54
55
  unhilight: () => void;
55
56
  }
56
57
 
57
- export interface VirtualListProps<T> {
58
+ export interface VirtualListProps<T> extends TestProps {
58
59
  children: (props: {
59
- data: T;
60
+ item: T;
60
61
  index: number;
61
62
  isLast: boolean;
62
63
  }) => ReactElement;
@@ -73,6 +74,8 @@ export interface VirtualListProps<T> {
73
74
  * full width list
74
75
  */
75
76
  fullWidth?: boolean;
77
+ maxWidth?: string | number;
78
+ minWidth?: string | number;
76
79
  /**
77
80
  * padding
78
81
  */
@@ -85,6 +88,7 @@ export interface VirtualListProps<T> {
85
88
  * data list
86
89
  */
87
90
  items: T[];
91
+ total?: number;
88
92
  initialScroll?: number;
89
93
  /**
90
94
  * loading state
@@ -97,7 +101,7 @@ export interface VirtualListProps<T> {
97
101
  /**
98
102
  * load more callback
99
103
  */
100
- onLoadMore?: (page?: number) => void;
104
+ onLoadMore?: (lastIndex?: number) => void;
101
105
  /**
102
106
  * scroll handler
103
107
  */
@@ -106,10 +110,13 @@ export interface VirtualListProps<T> {
106
110
 
107
111
  const createItemList = memoizeOne((items) => items);
108
112
 
109
- const _VirtualList = <T extends KeyValue>({
113
+ const _VirtualList = <T extends AnyObject>({
110
114
  items,
115
+ total = 0,
111
116
  children,
112
117
  fullWidth,
118
+ maxWidth,
119
+ minWidth,
113
120
  padding = "md",
114
121
  orientation = "vertical",
115
122
  defaultHeight: height = 48,
@@ -120,20 +127,21 @@ const _VirtualList = <T extends KeyValue>({
120
127
  onLoadMore,
121
128
  onScroll,
122
129
  listRef,
130
+ ...aria
123
131
  }: VirtualListProps<T>) => {
124
132
  const count = useDeferredValue(items.length);
125
- const extraSize = useMemo(() => (onLoadMore ? 64 : 0), [onLoadMore]);
133
+ const extraSize = useMemo(() => (onLoadMore ? 8 : 0), [onLoadMore]);
126
134
  const itemList: Array<{
127
135
  index: number;
128
136
  data: T;
129
137
  isLast: boolean;
130
138
  isSticky: boolean;
131
139
  }> = createItemList(
132
- items.map((item: AnyObject, idx) => {
140
+ items.map((item: AnyObject, index) => {
133
141
  return {
134
- index: idx,
135
- data: item,
136
- isLast: idx + 1 === items.length,
142
+ index,
143
+ item,
144
+ isLast: index + 1 === items.length,
137
145
  };
138
146
  }),
139
147
  );
@@ -141,6 +149,7 @@ const _VirtualList = <T extends KeyValue>({
141
149
  const scrollerRef = useRef<HTMLDivElement>(null);
142
150
  const virtualizer = useVirtualizer({
143
151
  count,
152
+ overscan: 2,
144
153
  horizontal: orientation === "horizontal",
145
154
  getScrollElement: () => scrollerRef.current,
146
155
  estimateSize: () => (orientation === "horizontal" ? width : height),
@@ -199,22 +208,22 @@ const _VirtualList = <T extends KeyValue>({
199
208
  }, [itemList, calculateActiveScroll]);
200
209
 
201
210
  useEffect(() => {
202
- const db = debounce(() => {
203
- const lastItem = virtualItems?.slice(-1).pop();
204
- if (lastItem && !loading && lastItem.index === count - 1) onLoadMore?.();
205
- });
206
- db();
207
- return () => db.cancel();
208
- }, [onLoadMore, loading, itemList, virtualItems, count]);
209
-
210
- useEffect(() => {
211
- const firstItem = virtualItems[0]?.index;
212
- if (onLoadMore && firstItem !== undefined && items[firstItem] === null) {
211
+ if (onLoadMore) {
212
+ const firstItem = virtualItems[0]?.index;
213
+ const lastItem = virtualItems?.slice(-1).pop()?.index;
214
+ const canLoadPrevPage =
215
+ firstItem !== undefined && items[firstItem] === null;
216
+ const canLoadNextPage =
217
+ lastItem !== undefined && lastItem === count - 1 && count < total;
213
218
  const db = debounce(onLoadMore);
214
- db(firstItem);
219
+ if (canLoadPrevPage) {
220
+ db(firstItem);
221
+ } else if (!loading && canLoadNextPage) {
222
+ db(lastItem + 1);
223
+ }
215
224
  return () => db.cancel();
216
225
  }
217
- }, [onLoadMore, items, virtualItems, count]);
226
+ }, [onLoadMore, virtualItems]);
218
227
 
219
228
  useLayoutEffect(() => {
220
229
  setTimeout(() => {
@@ -227,14 +236,14 @@ const _VirtualList = <T extends KeyValue>({
227
236
  listRef,
228
237
  () => ({
229
238
  scrollToItem(index) {
230
- virtualizer.scrollToIndex(index, { align: "start" });
239
+ virtualizer.scrollToIndex(index, { align: "auto" });
231
240
  },
232
241
  hilight(index) {
233
242
  scrollerRef.current
234
243
  ?.querySelector(".hilight")
235
244
  ?.classList.remove("hilight", "ring-1");
236
245
  virtualizer.scrollToIndex(Math.floor(index), {
237
- align: "start",
246
+ align: "auto",
238
247
  });
239
248
  setTimeout(() => {
240
249
  scrollerRef.current
@@ -255,13 +264,12 @@ const _VirtualList = <T extends KeyValue>({
255
264
  <div
256
265
  ref={scrollerRef}
257
266
  onScroll={handleScroll}
258
- className={classNames(
259
- "area-content bg-base overflow-auto contain-strict",
260
- )}
267
+ className={classNames("area-content bg-base overflow-auto")}
268
+ {...aria}
261
269
  >
262
270
  <div
263
271
  className={classNames(
264
- "inline-flex flex-nowrap gap-2 justify-center min-h-full min-w-full",
272
+ "flex flex-nowrap gap-2 justify-center min-h-full min-w-full",
265
273
  orientation === "horizontal" && "flex-col",
266
274
  )}
267
275
  >
@@ -275,12 +283,16 @@ const _VirtualList = <T extends KeyValue>({
275
283
  padding === "md" && "p-2",
276
284
  padding === "lg" && "p-4",
277
285
  )}
286
+ style={{
287
+ minWidth,
288
+ maxWidth,
289
+ }}
278
290
  >
279
291
  <div
280
292
  style={
281
293
  orientation === "vertical"
282
- ? { height: virtualizer.getTotalSize() }
283
- : { width: virtualizer.getTotalSize() }
294
+ ? { height: virtualizer.getTotalSize() + extraSize }
295
+ : { width: virtualizer.getTotalSize() + extraSize }
284
296
  }
285
297
  >
286
298
  <div
@@ -304,9 +316,9 @@ const _VirtualList = <T extends KeyValue>({
304
316
  </div>
305
317
  ))}
306
318
  </div>
307
- {onLoadMore && (
308
- <div className={orientation === "horizontal" ? "min-w-16" : "h-16"}>
309
- {loading && <Skeleton />}
319
+ {loading && (
320
+ <div className={orientation === "horizontal" ? "min-w-16" : ""}>
321
+ <Skeleton />
310
322
  </div>
311
323
  )}
312
324
  </div>
@@ -348,4 +360,41 @@ const _VirtualList = <T extends KeyValue>({
348
360
  _VirtualList.displayName = "VirtualList";
349
361
 
350
362
  const GenericMemo: <T>(c: T) => T = memo;
363
+
364
+ /**
365
+ * VirtualList component for rendering large lists efficiently using virtualization.
366
+ * It supports horizontal and vertical orientations, custom item heights and widths,
367
+ * and provides a scroller for navigating through the list.
368
+ * It also supports loading more items on scroll and provides a way to hilight items.
369
+ * It can be used with a ref to control scrolling and hilighting of items.
370
+ *
371
+ * @param {VirtualListProps<T>} props - The properties for the VirtualList component.
372
+ * @returns {JSX.Element} The rendered VirtualList component.
373
+ * @template T - The type of items in the list, extending AnyObject.
374
+ *
375
+ * @example
376
+ * ```jsx
377
+ * <VirtualList
378
+ * items={items}
379
+ * children={({ item, index, isLast }) => (
380
+ * <div key={index} className="item">
381
+ * {item.label}
382
+ * </div>
383
+ * )}
384
+ * fullWidth={true}
385
+ * orientation="vertical"
386
+ * defaultHeight={50}
387
+ * onLoadMore={(lastIndex) => console.log("Load more items from index:", lastIndex)}
388
+ * onScroll={(top) => console.log("Scrolled to top:", top)}
389
+ * listRef={virtualListRef}
390
+ * >
391
+ * {({ item, index, isLast }) => (
392
+ * <div className="gallery-item" key={item.id}>
393
+ * <img src={item.image} alt={item.label} />
394
+ * <p>{item.label}</p>
395
+ * </div>
396
+ * )}
397
+ * </VirtualList>
398
+ * ```
399
+ */
351
400
  export const VirtualList = GenericMemo(_VirtualList);
@@ -1 +0,0 @@
1
- @layer comp{.histogram{.histoLabel{--tw-gradient-from:var(--color) var(--tw-gradient-from-position);--tw-gradient-to:color-mix(in lab,var(--color) 20%,var(--fabric-bg)) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to);background-color:color(from var(--color) srgb r g b/5%);&:hover{background-color:color(from var(--color) srgb r g b/15%)}&[data-disabled=true]{--color:theme(colors.tint.300);color:theme(colors.tint.600)}}.histoBar{box-shadow:-2px 0 0 var(--color) inset;:global([dir=rtl]) &{box-shadow:2px 0 0 var(--color) inset}}.histoBadge{background-color:color(from var(--color) srgb r g b/15%)}}}
@@ -1 +0,0 @@
1
- @layer comp{.histogram{.histoLabel{--tw-gradient-from:var(--color) var(--tw-gradient-from-position);--tw-gradient-to:color-mix(in lab,var(--color) 20%,var(--fabric-bg)) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to);background-color:color(from var(--color) srgb r g b/5%);&:hover{background-color:color(from var(--color) srgb r g b/15%)}&[data-disabled=true]{--color:theme(colors.tint.300);color:theme(colors.tint.600)}}.histoBar{box-shadow:-2px 0 0 var(--color) inset;:global([dir=rtl]) &{box-shadow:2px 0 0 var(--color) inset}}.histoBadge{background-color:color(from var(--color) srgb r g b/15%)}}}