@praxisjs/composables 1.2.1 → 1.2.3

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 (52) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/browser.d.ts +41 -18
  3. package/dist/browser.d.ts.map +1 -1
  4. package/dist/browser.js +114 -114
  5. package/dist/browser.js.map +1 -1
  6. package/dist/dom.d.ts +24 -16
  7. package/dist/dom.d.ts.map +1 -1
  8. package/dist/dom.js +75 -84
  9. package/dist/dom.js.map +1 -1
  10. package/dist/list.d.ts +4 -1
  11. package/dist/list.d.ts.map +1 -1
  12. package/dist/list.js +29 -11
  13. package/dist/list.js.map +1 -1
  14. package/dist/upload.d.ts.map +1 -1
  15. package/dist/upload.js +32 -12
  16. package/dist/upload.js.map +1 -1
  17. package/dist/utilities.d.ts +13 -1
  18. package/dist/utilities.d.ts.map +1 -1
  19. package/dist/utilities.js +88 -26
  20. package/dist/utilities.js.map +1 -1
  21. package/package.json +14 -5
  22. package/src/browser.ts +129 -115
  23. package/src/dom.ts +77 -85
  24. package/src/list.ts +29 -10
  25. package/src/upload.ts +30 -11
  26. package/src/utilities.ts +101 -24
  27. package/dist/__tests__/browser.test.d.ts +0 -2
  28. package/dist/__tests__/browser.test.d.ts.map +0 -1
  29. package/dist/__tests__/browser.test.js +0 -350
  30. package/dist/__tests__/browser.test.js.map +0 -1
  31. package/dist/__tests__/dom.test.d.ts +0 -2
  32. package/dist/__tests__/dom.test.d.ts.map +0 -1
  33. package/dist/__tests__/dom.test.js +0 -463
  34. package/dist/__tests__/dom.test.js.map +0 -1
  35. package/dist/__tests__/list.test.d.ts +0 -2
  36. package/dist/__tests__/list.test.d.ts.map +0 -1
  37. package/dist/__tests__/list.test.js +0 -156
  38. package/dist/__tests__/list.test.js.map +0 -1
  39. package/dist/__tests__/upload.test.d.ts +0 -2
  40. package/dist/__tests__/upload.test.d.ts.map +0 -1
  41. package/dist/__tests__/upload.test.js +0 -531
  42. package/dist/__tests__/upload.test.js.map +0 -1
  43. package/dist/__tests__/utilities.test.d.ts +0 -2
  44. package/dist/__tests__/utilities.test.d.ts.map +0 -1
  45. package/dist/__tests__/utilities.test.js +0 -251
  46. package/dist/__tests__/utilities.test.js.map +0 -1
  47. package/src/__tests__/browser.test.ts +0 -414
  48. package/src/__tests__/dom.test.ts +0 -567
  49. package/src/__tests__/list.test.ts +0 -210
  50. package/src/__tests__/upload.test.ts +0 -639
  51. package/src/__tests__/utilities.test.ts +0 -327
  52. package/tsconfig.json +0 -8
@@ -1,210 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { describe, it, expect, vi } from "vitest";
3
-
4
- import { signal } from "@praxisjs/core/internal";
5
-
6
- // Import from index to cover re-exports
7
- import { VirtualList, type VirtualItem } from "../index";
8
-
9
- type AnyItem = { id: number };
10
-
11
- function makeItems(count: number): AnyItem[] {
12
- return Array.from({ length: count }, (_, i) => ({ id: i }));
13
- }
14
-
15
- // ── VirtualList ───────────────────────────────────────────────────────────────
16
-
17
- describe("VirtualList", () => {
18
- const ITEM_HEIGHT = 50;
19
- const VIEW_HEIGHT = 600;
20
- const BUFFER = 3;
21
-
22
- it("setup() returns computed signals for all four properties", () => {
23
- const ref = { current: null };
24
- const vl = new VirtualList(ref, () => makeItems(10), ITEM_HEIGHT);
25
- const view = vl.setup() as {
26
- visibleItems: () => VirtualItem<AnyItem>[];
27
- totalHeight: () => number;
28
- offsetTop: () => number;
29
- offsetBottom: () => number;
30
- };
31
-
32
- expect(typeof view.visibleItems).toBe("function");
33
- expect(typeof view.totalHeight).toBe("function");
34
- expect(typeof view.offsetTop).toBe("function");
35
- expect(typeof view.offsetBottom).toBe("function");
36
- });
37
-
38
- it("totalHeight = items.length * itemHeight", () => {
39
- const ref = { current: null };
40
- const vl = new VirtualList(ref, () => makeItems(100), ITEM_HEIGHT);
41
- const { totalHeight } = vl.setup() as { totalHeight: () => number };
42
- expect(totalHeight()).toBe(100 * ITEM_HEIGHT);
43
- });
44
-
45
- it("offsetTop = 0 when scrolled to top", () => {
46
- const ref = { current: null };
47
- const vl = new VirtualList(ref, () => makeItems(100), ITEM_HEIGHT);
48
- const { offsetTop } = vl.setup() as { offsetTop: () => number };
49
- expect(offsetTop()).toBe(0);
50
- });
51
-
52
- it("visibleItems starts at index 0 with buffer window", () => {
53
- const ref = { current: null };
54
- // default viewHeight=600, buffer=3, scrollTop=0
55
- // startIdx = max(0, floor(0/50) - 3) = 0
56
- // endIdx = min(99, ceil((0+600)/50) + 3) = min(99, 12+3) = 15
57
- const vl = new VirtualList(ref, () => makeItems(100), ITEM_HEIGHT, BUFFER);
58
- const { visibleItems } = vl.setup() as { visibleItems: () => VirtualItem<AnyItem>[] };
59
-
60
- const items = visibleItems();
61
- expect(items[0].index).toBe(0);
62
- expect(items[items.length - 1].index).toBe(15);
63
- });
64
-
65
- it("visibleItems contains the correct item references", () => {
66
- const source = makeItems(20);
67
- const ref = { current: null };
68
- const vl = new VirtualList(ref, () => source, ITEM_HEIGHT, 0);
69
- const { visibleItems } = vl.setup() as { visibleItems: () => VirtualItem<AnyItem>[] };
70
-
71
- const items = visibleItems();
72
- expect(items[0].item).toBe(source[0]);
73
- expect(items[0].index).toBe(0);
74
- });
75
-
76
- it("offsetBottom reflects the hidden rows below the window", () => {
77
- const ref = { current: null };
78
- // startIdx=0, endIdx=15, total=100
79
- // offsetBottom = max(0, 100-1-15) * 50 = 84 * 50 = 4200
80
- const vl = new VirtualList(ref, () => makeItems(100), ITEM_HEIGHT, BUFFER);
81
- const { offsetBottom } = vl.setup() as { offsetBottom: () => number };
82
- expect(offsetBottom()).toBe((100 - 1 - 15) * ITEM_HEIGHT);
83
- });
84
-
85
- it("empty list: all offsets are 0 and visibleItems is empty", () => {
86
- const ref = { current: null };
87
- const vl = new VirtualList(ref, () => [], ITEM_HEIGHT);
88
- const { visibleItems, totalHeight, offsetTop, offsetBottom } = vl.setup() as {
89
- visibleItems: () => VirtualItem<AnyItem>[];
90
- totalHeight: () => number;
91
- offsetTop: () => number;
92
- offsetBottom: () => number;
93
- };
94
-
95
- expect(visibleItems()).toHaveLength(0);
96
- expect(totalHeight()).toBe(0);
97
- expect(offsetTop()).toBe(0);
98
- expect(offsetBottom()).toBe(0);
99
- });
100
- });
101
-
102
- // ── VirtualList — onMount ─────────────────────────────────────────────────────
103
-
104
- describe("VirtualList — onMount", () => {
105
- const ITEM_HEIGHT = 50;
106
-
107
- it("onMount() with null ref is a no-op", () => {
108
- const ref = { current: null };
109
- const vl = new VirtualList(ref, () => makeItems(10), ITEM_HEIGHT);
110
- vl.setup();
111
- expect(() => vl.onMount()).not.toThrow();
112
- });
113
-
114
- it("onMount() sets viewHeight from container's clientHeight when > 0", () => {
115
- const el = document.createElement("div");
116
- Object.defineProperty(el, "clientHeight", { value: 400, configurable: true });
117
-
118
- const ref = { current: el };
119
- const vl = new VirtualList(ref, () => makeItems(100), ITEM_HEIGHT, 0);
120
- const { visibleItems } = vl.setup() as { visibleItems: () => VirtualItem<AnyItem>[] };
121
- vl.onMount();
122
-
123
- // With viewHeight=400 and no buffer: endIdx = min(99, ceil(400/50)-1) = 7
124
- // Visible range [0..7] = 8 items
125
- const items = visibleItems();
126
- expect(items.length).toBeLessThan(100);
127
- expect(items.length).toBeGreaterThan(0);
128
- // Specifically: ceil((0+400)/50) + 0 = 8; min(99, 8) = 8 → indices 0..8 = 9 items
129
- expect(items[items.length - 1].index).toBe(8);
130
- });
131
-
132
- it("onMount() does not override default viewHeight when clientHeight is 0", () => {
133
- const el = document.createElement("div");
134
- Object.defineProperty(el, "clientHeight", { value: 0, configurable: true });
135
-
136
- const ref = { current: el };
137
- const vl = new VirtualList(ref, () => makeItems(100), ITEM_HEIGHT, 0);
138
- const { visibleItems } = vl.setup() as { visibleItems: () => VirtualItem<AnyItem>[] };
139
- vl.onMount();
140
-
141
- // Default viewHeight=600 preserved; endIdx = min(99, ceil(600/50)) = 12
142
- const items = visibleItems();
143
- expect(items[items.length - 1].index).toBe(12);
144
- });
145
-
146
- it("onMount() registers a scroll listener that updates the window", () => {
147
- const el = document.createElement("div");
148
- Object.defineProperty(el, "clientHeight", { value: 0, configurable: true });
149
-
150
- const ref = { current: el };
151
- const vl = new VirtualList(ref, () => makeItems(100), ITEM_HEIGHT, 0);
152
- const { offsetTop } = vl.setup() as { offsetTop: () => number };
153
- vl.onMount();
154
-
155
- expect(offsetTop()).toBe(0);
156
-
157
- Object.defineProperty(el, "scrollTop", { value: 500, configurable: true });
158
- el.dispatchEvent(new Event("scroll"));
159
-
160
- // scrollTop=500, buffer=0: startIdx = floor(500/50) = 10; offsetTop = 10*50 = 500
161
- expect(offsetTop()).toBe(500);
162
- });
163
- });
164
-
165
- // ── VirtualList — onUnmount ───────────────────────────────────────────────────
166
-
167
- describe("VirtualList — onUnmount", () => {
168
- const ITEM_HEIGHT = 50;
169
-
170
- it("onUnmount() removes the scroll listener", () => {
171
- const el = document.createElement("div");
172
- const remove = vi.spyOn(el, "removeEventListener");
173
-
174
- const ref = { current: el };
175
- const vl = new VirtualList(ref, () => makeItems(50), ITEM_HEIGHT);
176
- vl.setup();
177
- vl.onMount();
178
- vl.onUnmount();
179
-
180
- expect(remove).toHaveBeenCalledWith("scroll", expect.any(Function));
181
- });
182
-
183
- it("onUnmount() without prior onMount() does not throw", () => {
184
- const ref = { current: null };
185
- const vl = new VirtualList(ref, () => makeItems(10), ITEM_HEIGHT);
186
- vl.setup();
187
- expect(() => vl.onUnmount()).not.toThrow();
188
- });
189
- });
190
-
191
- // ── VirtualList — reactive getItems ──────────────────────────────────────────
192
-
193
- describe("VirtualList — reactive getItems", () => {
194
- it("visibleItems updates when the source signal changes", () => {
195
- const itemsSignal = signal(makeItems(5));
196
- const ref = { current: null };
197
- const vl = new VirtualList(ref, () => itemsSignal(), 50);
198
- const { visibleItems, totalHeight } = vl.setup() as {
199
- visibleItems: () => VirtualItem<AnyItem>[];
200
- totalHeight: () => number;
201
- };
202
-
203
- expect(totalHeight()).toBe(250);
204
- expect(visibleItems()).toHaveLength(5);
205
-
206
- itemsSignal.set(makeItems(10));
207
- expect(totalHeight()).toBe(500);
208
- expect(visibleItems()).toHaveLength(10);
209
- });
210
- });