@rudra-studio/rudra-layout 1.0.18 → 1.0.19

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.
@@ -0,0 +1,94 @@
1
+ import { default as React } from 'react';
2
+ export interface VirtualListRenderContext {
3
+ item: any;
4
+ index: number;
5
+ }
6
+ export interface VirtualListProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children" | "className"> {
7
+ /**
8
+ * List data.
9
+ *
10
+ * @type|json
11
+ */
12
+ items?: any[];
13
+ /**
14
+ * Item renderer.
15
+ *
16
+ * @nodeFunction
17
+ */
18
+ children?: React.ReactNode | ((context: VirtualListRenderContext) => React.ReactNode);
19
+ /**
20
+ * Height of one item in pixels.
21
+ */
22
+ itemHeight?: number;
23
+ /**
24
+ * Visible list height.
25
+ */
26
+ height?: number;
27
+ /**
28
+ * Additional items rendered above
29
+ * and below the viewport.
30
+ */
31
+ overscan?: number;
32
+ /**
33
+ * Gap between rows.
34
+ */
35
+ gap?: number;
36
+ /**
37
+ * Index to scroll to.
38
+ *
39
+ * Updating this prop scrolls
40
+ * the list to that item.
41
+ */
42
+ scrollToIndex?: number;
43
+ /**
44
+ * @select|start|center|end
45
+ */
46
+ scrollAlignment?: "start" | "center" | "end";
47
+ /**
48
+ * Initial scroll index.
49
+ */
50
+ initialScrollIndex?: number;
51
+ /**
52
+ * Trigger onEndReached when this many
53
+ * items remain below the visible range.
54
+ */
55
+ endReachedThreshold?: number;
56
+ /**
57
+ * Empty builder message.
58
+ */
59
+ emptyText?: string;
60
+ /**
61
+ * @type|class
62
+ */
63
+ className?: string;
64
+ /**
65
+ * @type|class
66
+ */
67
+ itemClassName?: string;
68
+ /**
69
+ * @type|class
70
+ */
71
+ contentClassName?: string;
72
+ /**
73
+ * @type|complex
74
+ * @schema {"type":"object"}
75
+ */
76
+ customAttributes?: Record<string, string>;
77
+ /**
78
+ * @type|function
79
+ */
80
+ onScrollChange?: (scrollTop: number) => void;
81
+ /**
82
+ * @type|function
83
+ */
84
+ onVisibleRangeChange?: (startIndex: number, endIndex: number) => void;
85
+ /**
86
+ * @type|function
87
+ */
88
+ onEndReached?: () => void;
89
+ /**
90
+ * @type|function
91
+ */
92
+ onItemClick?: (item: any, index: number) => void;
93
+ }
94
+ export default function VirtualList({ items, children, itemHeight, height, overscan, gap, scrollToIndex, scrollAlignment, initialScrollIndex, endReachedThreshold, emptyText, className, itemClassName, contentClassName, customAttributes, onScrollChange, onVisibleRangeChange, onEndReached, onItemClick, style, ...props }: VirtualListProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,127 @@
1
+ import { useEffect as e, useMemo as t, useRef as n, useState as r } from "react";
2
+ import { jsx as i } from "react/jsx-runtime";
3
+ //#region src/components/VirtualList/index.tsx
4
+ function a(e, t, n) {
5
+ return Math.max(t, Math.min(n, e));
6
+ }
7
+ function o({ items: o = [], children: s, itemHeight: c = 56, height: l = 400, overscan: u = 3, gap: d = 0, scrollToIndex: f, scrollAlignment: p = "start", initialScrollIndex: m = 0, endReachedThreshold: h = 3, emptyText: g = "Add list items", className: _ = "w-full", itemClassName: v = "", contentClassName: y = "", customAttributes: b = {}, onScrollChange: x, onVisibleRangeChange: S, onEndReached: C, onItemClick: w, style: T, ...E }) {
8
+ let D = n(null), O = n(!1), [k, A] = r(0), j = Math.max(1, c), M = Math.max(0, d), N = j + M, P = o.length > 0 ? o.length * N - M : 0, F = Math.max(1, Math.ceil(l / N)), I = Math.floor(k / N), L = a(I - Math.max(0, u), 0, Math.max(0, o.length - 1)), R = a(I + F + Math.max(0, u), 0, Math.max(0, o.length - 1)), z = t(() => {
9
+ if (o.length === 0) return [];
10
+ let e = [];
11
+ for (let t = L; t <= R; t++) e.push({
12
+ item: o[t],
13
+ index: t
14
+ });
15
+ return e;
16
+ }, [
17
+ o,
18
+ L,
19
+ R
20
+ ]), B = (e) => {
21
+ let t = a(e, 0, Math.max(0, o.length - 1)) * N;
22
+ return p === "center" ? Math.max(0, t - l / 2 + j / 2) : p === "end" ? Math.max(0, t - l + j) : t;
23
+ }, V = (e, t = "auto") => {
24
+ let n = D.current;
25
+ !n || o.length === 0 || n.scrollTo({
26
+ top: B(e),
27
+ behavior: t
28
+ });
29
+ };
30
+ return e(() => {
31
+ if (o.length === 0 || m <= 0) return;
32
+ let e = requestAnimationFrame(() => {
33
+ V(m);
34
+ });
35
+ return () => {
36
+ cancelAnimationFrame(e);
37
+ };
38
+ }, []), e(() => {
39
+ f !== void 0 && V(f, "smooth");
40
+ }, [
41
+ f,
42
+ o.length,
43
+ N,
44
+ l,
45
+ p
46
+ ]), e(() => {
47
+ if (o.length === 0) return;
48
+ let e = a(I, 0, o.length - 1), t = a(I + F - 1, 0, o.length - 1);
49
+ S?.(e, t), o.length - 1 - t <= Math.max(0, h) ? O.current || (O.current = !0, C?.()) : O.current = !1;
50
+ }, [
51
+ I,
52
+ F,
53
+ o.length,
54
+ h
55
+ ]), o.length === 0 ? /* @__PURE__ */ i("div", {
56
+ className: _,
57
+ ...b,
58
+ ...E,
59
+ style: {
60
+ width: "100%",
61
+ height: l,
62
+ display: "flex",
63
+ alignItems: "center",
64
+ justifyContent: "center",
65
+ padding: 16,
66
+ border: "1px dashed #d1d5db",
67
+ borderRadius: 8,
68
+ color: "#9ca3af",
69
+ fontSize: 13,
70
+ boxSizing: "border-box",
71
+ ...T
72
+ },
73
+ children: typeof s == "function" ? s({
74
+ item: null,
75
+ index: 0
76
+ }) : g
77
+ }) : /* @__PURE__ */ i("div", {
78
+ ref: D,
79
+ className: _,
80
+ ...b,
81
+ ...E,
82
+ onScroll: (e) => {
83
+ let t = e.currentTarget.scrollTop;
84
+ A(t), x?.(t);
85
+ },
86
+ style: {
87
+ position: "relative",
88
+ width: "100%",
89
+ height: l,
90
+ overflowY: "auto",
91
+ overflowX: "hidden",
92
+ WebkitOverflowScrolling: "touch",
93
+ boxSizing: "border-box",
94
+ ...T
95
+ },
96
+ children: /* @__PURE__ */ i("div", {
97
+ className: y,
98
+ style: {
99
+ position: "relative",
100
+ width: "100%",
101
+ height: P,
102
+ minHeight: P,
103
+ boxSizing: "border-box"
104
+ },
105
+ children: z.map(({ item: e, index: t }) => /* @__PURE__ */ i("div", {
106
+ className: v,
107
+ "data-index": t,
108
+ onClick: () => w?.(e, t),
109
+ style: {
110
+ position: "absolute",
111
+ top: t * N,
112
+ left: 0,
113
+ right: 0,
114
+ height: j,
115
+ overflow: "hidden",
116
+ boxSizing: "border-box"
117
+ },
118
+ children: typeof s == "function" ? s({
119
+ item: e,
120
+ index: t
121
+ }) : s
122
+ }, e?.id ?? t))
123
+ })
124
+ });
125
+ }
126
+ //#endregion
127
+ export { o as default };
package/index.d.ts CHANGED
@@ -26,3 +26,5 @@ export type { ComplexGridProps } from './components/StructuredGrid';
26
26
  export { default as ComplexGrid } from './components/StructuredGrid';
27
27
  export type { DataTableProps } from './components/Table';
28
28
  export { default as DataTable } from './components/Table';
29
+ export type { VirtualListProps, VirtualListRenderContext } from './components/VirtualList';
30
+ export { default as VirtualList } from './components/VirtualList';
package/index.js CHANGED
@@ -12,4 +12,5 @@ import u from "./components/Section/index.js";
12
12
  import d from "./components/Stack/index.js";
13
13
  import f from "./components/StructuredGrid/index.js";
14
14
  import p from "./components/Table/index.js";
15
- export { e as AspectRatio, t as Box, f as ComplexGrid, r as Container, p as DataTable, a as Flex, o as Grid, s as Repeater, i as RepeaterCarousel, c as RepeaterTable, n as RudraCarousel, l as ScrollArea, u as Section, d as Stack };
15
+ import m from "./components/VirtualList/index.js";
16
+ export { e as AspectRatio, t as Box, f as ComplexGrid, r as Container, p as DataTable, a as Flex, o as Grid, s as Repeater, i as RepeaterCarousel, c as RepeaterTable, n as RudraCarousel, l as ScrollArea, u as Section, d as Stack, m as VirtualList };
package/package.json CHANGED
@@ -42,5 +42,5 @@
42
42
  },
43
43
  "types": "./index.d.ts",
44
44
  "unpkg": "./index.umd.js",
45
- "version": "1.0.18"
45
+ "version": "1.0.19"
46
46
  }