@pdanpdan/virtual-scroll 0.2.1 → 0.4.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.
@@ -0,0 +1,148 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { getPaddingX, getPaddingY, isBody, isElement, isScrollableElement, isScrollToIndexOptions, isWindow, isWindowLike } from './scroll';
4
+
5
+ describe('scroll utils', () => {
6
+ describe('isWindow', () => {
7
+ it('should return true for null', () => {
8
+ expect(isWindow(null)).toBe(true);
9
+ });
10
+
11
+ it('should return true for window object', () => {
12
+ expect(isWindow(window)).toBe(true);
13
+ });
14
+
15
+ it('should return false for an element', () => {
16
+ const el = document.createElement('div');
17
+ expect(isWindow(el)).toBe(false);
18
+ });
19
+ });
20
+
21
+ describe('isBody', () => {
22
+ it('should return true for document.body', () => {
23
+ expect(isBody(document.body)).toBe(true);
24
+ });
25
+
26
+ it('should return false for null', () => {
27
+ expect(isBody(null)).toBe(false);
28
+ });
29
+
30
+ it('should return false for undefined', () => {
31
+ expect(isBody(undefined)).toBe(false);
32
+ });
33
+
34
+ it('should return false for a string', () => {
35
+ // @ts-expect-error testing invalid input
36
+ expect(isBody('not an object')).toBe(false);
37
+ });
38
+
39
+ it('should return false for a plain object', () => {
40
+ // @ts-expect-error testing invalid input
41
+ expect(isBody({})).toBe(false);
42
+ });
43
+
44
+ it('should return false for a div', () => {
45
+ const el = document.createElement('div');
46
+ expect(isBody(el)).toBe(false);
47
+ });
48
+
49
+ it('should return false for window', () => {
50
+ expect(isBody(window)).toBe(false);
51
+ });
52
+ });
53
+
54
+ describe('isWindowLike', () => {
55
+ it('should return true for window', () => {
56
+ expect(isWindowLike(window)).toBe(true);
57
+ });
58
+
59
+ it('should return true for body', () => {
60
+ expect(isWindowLike(document.body)).toBe(true);
61
+ });
62
+
63
+ it('should return true for null', () => {
64
+ expect(isWindowLike(null)).toBe(true);
65
+ });
66
+
67
+ it('should return false for a div', () => {
68
+ const el = document.createElement('div');
69
+ expect(isWindowLike(el)).toBe(false);
70
+ });
71
+ });
72
+
73
+ describe('isElement', () => {
74
+ it('should return true for a div', () => {
75
+ const el = document.createElement('div');
76
+ expect(isElement(el)).toBe(true);
77
+ });
78
+
79
+ it('should return false for window', () => {
80
+ expect(isElement(window)).toBe(false);
81
+ });
82
+
83
+ it('should return false for null', () => {
84
+ expect(isElement(null)).toBe(false);
85
+ });
86
+ });
87
+
88
+ describe('isScrollableElement', () => {
89
+ it('should return true for a div', () => {
90
+ const el = document.createElement('div');
91
+ expect(isScrollableElement(el)).toBe(true);
92
+ });
93
+
94
+ it('should return false for null', () => {
95
+ expect(isScrollableElement(null)).toBe(false);
96
+ });
97
+ });
98
+
99
+ describe('isScrollToIndexOptions', () => {
100
+ it('should return true for valid options', () => {
101
+ expect(isScrollToIndexOptions({ align: 'start' })).toBe(true);
102
+ expect(isScrollToIndexOptions({ behavior: 'smooth' })).toBe(true);
103
+ expect(isScrollToIndexOptions({ isCorrection: true })).toBe(true);
104
+ });
105
+
106
+ it('should return false for other values', () => {
107
+ expect(isScrollToIndexOptions(null)).toBe(false);
108
+ expect(isScrollToIndexOptions('start')).toBe(false);
109
+ expect(isScrollToIndexOptions({})).toBe(false);
110
+ });
111
+ });
112
+
113
+ describe('getPaddingX', () => {
114
+ it('should handle numeric padding', () => {
115
+ expect(getPaddingX(10, 'horizontal')).toBe(10);
116
+ expect(getPaddingX(10, 'both')).toBe(10);
117
+ expect(getPaddingX(10, 'vertical')).toBe(0);
118
+ expect(getPaddingX(0, 'horizontal')).toBe(0);
119
+ });
120
+
121
+ it('should handle object padding', () => {
122
+ expect(getPaddingX({ x: 15 }, 'vertical')).toBe(15);
123
+ expect(getPaddingX({ y: 20 }, 'horizontal')).toBe(0);
124
+ });
125
+
126
+ it('should return 0 for undefined', () => {
127
+ expect(getPaddingX(undefined)).toBe(0);
128
+ });
129
+ });
130
+
131
+ describe('getPaddingY', () => {
132
+ it('should handle numeric padding', () => {
133
+ expect(getPaddingY(10, 'vertical')).toBe(10);
134
+ expect(getPaddingY(10, 'both')).toBe(10);
135
+ expect(getPaddingY(10, 'horizontal')).toBe(0);
136
+ expect(getPaddingY(0, 'vertical')).toBe(0);
137
+ });
138
+
139
+ it('should handle object padding', () => {
140
+ expect(getPaddingY({ y: 15 }, 'horizontal')).toBe(15);
141
+ expect(getPaddingY({ x: 20 }, 'vertical')).toBe(0);
142
+ });
143
+
144
+ it('should return 0 for undefined', () => {
145
+ expect(getPaddingY(undefined)).toBe(0);
146
+ });
147
+ });
148
+ });
@@ -1,37 +1,67 @@
1
- import type { ScrollDirection, ScrollToIndexOptions } from '../composables/useVirtualScroll';
1
+ import type { ScrollDirection, ScrollToIndexOptions } from '../types';
2
2
 
3
3
  /**
4
- * Checks if the container has a bounding client rect method.
4
+ * Checks if the container is the window object.
5
5
  *
6
6
  * @param container - The container element or window to check.
7
- * @returns True if the container is an HTMLElement with getBoundingClientRect.
7
+ * @returns `true` if the container is the global window object.
8
+ */
9
+ export function isWindow(container: HTMLElement | Window | null | undefined): container is Window {
10
+ return container === null || (typeof window !== 'undefined' && container === window);
11
+ }
12
+
13
+ /**
14
+ * Checks if the container is the document body element.
15
+ *
16
+ * @param container - The container element or window to check.
17
+ * @returns `true` if the container is the `<body>` element.
18
+ */
19
+ export function isBody(container: HTMLElement | Window | null | undefined): container is HTMLElement {
20
+ return !!container && typeof container === 'object' && 'tagName' in container && container.tagName === 'BODY';
21
+ }
22
+
23
+ /**
24
+ * Checks if the container is window-like (global window or document body).
25
+ *
26
+ * @param container - The container element or window to check.
27
+ * @returns `true` if the container is window or body.
28
+ */
29
+ export function isWindowLike(container: HTMLElement | Window | null | undefined): boolean {
30
+ return isWindow(container) || isBody(container);
31
+ }
32
+
33
+ /**
34
+ * Checks if the container is a valid HTML Element with bounding rect support.
35
+ *
36
+ * @param container - The container to check.
37
+ * @returns `true` if the container is an `HTMLElement`.
8
38
  */
9
39
  export function isElement(container: HTMLElement | Window | null | undefined): container is HTMLElement {
10
40
  return !!container && 'getBoundingClientRect' in container;
11
41
  }
12
42
 
13
43
  /**
14
- * Checks if the target is an element with scroll properties.
44
+ * Checks if the target is an element that supports scrolling.
15
45
  *
16
46
  * @param target - The event target to check.
17
- * @returns True if the target is an HTMLElement with scroll properties.
47
+ * @returns `true` if the target is an `HTMLElement` with scroll properties.
18
48
  */
19
49
  export function isScrollableElement(target: EventTarget | null): target is HTMLElement {
20
50
  return !!target && 'scrollLeft' in target;
21
51
  }
22
52
 
23
53
  /**
24
- * Helper to determine if an options argument is the full ScrollToIndexOptions object.
54
+ * Helper to determine if an options argument is a full `ScrollToIndexOptions` object.
25
55
  *
26
56
  * @param options - The options object to check.
27
- * @returns True if the options object contains scroll-to-index specific properties.
57
+ * @returns `true` if the options object contains scroll-to-index specific properties.
28
58
  */
29
59
  export function isScrollToIndexOptions(options: unknown): options is ScrollToIndexOptions {
30
60
  return typeof options === 'object' && options !== null && ('align' in options || 'behavior' in options || 'isCorrection' in options);
31
61
  }
32
62
 
33
63
  /**
34
- * Extracts the horizontal padding from a padding value or object.
64
+ * Extracts the horizontal padding from a padding configuration.
35
65
  *
36
66
  * @param p - The padding value (number or object with x/y).
37
67
  * @param direction - The current scroll direction.
@@ -41,11 +71,11 @@ export function getPaddingX(p: number | { x?: number; y?: number; } | undefined,
41
71
  if (typeof p === 'object' && p !== null) {
42
72
  return p.x || 0;
43
73
  }
44
- return direction === 'horizontal' ? (p || 0) : 0;
74
+ return (direction === 'horizontal' || direction === 'both') ? (p || 0) : 0;
45
75
  }
46
76
 
47
77
  /**
48
- * Extracts the vertical padding from a padding value or object.
78
+ * Extracts the vertical padding from a padding configuration.
49
79
  *
50
80
  * @param p - The padding value (number or object with x/y).
51
81
  * @param direction - The current scroll direction.