kerfjs 4.4.0 → 5.0.0-beta.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.
- package/CHANGELOG.md +116 -0
- package/LICENSE +1 -1
- package/README.md +34 -35
- package/ai/cursorrules +46 -1
- package/ai/manifest.json +62 -5
- package/ai/skill.md +53 -2
- package/dist/actions.d.ts +1 -1
- package/dist/actions.js +4 -4
- package/dist/actions.js.map +1 -1
- package/dist/array-signal.js +5 -5
- package/dist/async.js +17 -10
- package/dist/async.js.map +1 -1
- package/dist/attach.d.ts +11 -8
- package/dist/attach.js +52 -4
- package/dist/attach.js.map +1 -1
- package/dist/chunk-GY4XV2UV.js +1 -1
- package/dist/{chunk-VVDJLWMP.js → chunk-HW7KSM2Y.js} +2 -2
- package/dist/chunk-HW7KSM2Y.js.map +1 -0
- package/dist/{chunk-KEZTD6H4.js → chunk-KPXIOG2C.js} +3 -3
- package/dist/{chunk-KEZTD6H4.js.map → chunk-KPXIOG2C.js.map} +1 -1
- package/dist/{chunk-SAYPJ6XR.js → chunk-KZJXHFIB.js} +10 -6
- package/dist/chunk-KZJXHFIB.js.map +1 -0
- package/dist/{chunk-MRYM3O3V.js → chunk-LVH3GC6B.js} +11 -8
- package/dist/chunk-LVH3GC6B.js.map +1 -0
- package/dist/chunk-QIP723L4.js +1 -1
- package/dist/{chunk-SRWQKB33.js → chunk-SVATPF5R.js} +97 -74
- package/dist/chunk-SVATPF5R.js.map +1 -0
- package/dist/{chunk-3APBEVHF.js → chunk-U6FK33SG.js} +3 -3
- package/dist/{chunk-3APBEVHF.js.map → chunk-U6FK33SG.js.map} +1 -1
- package/dist/{chunk-U32TFTGZ.js → chunk-UZJ6I4T6.js} +3 -3
- package/dist/chunk-UZJ6I4T6.js.map +1 -0
- package/dist/{chunk-YHH7OUFA.js → chunk-V46JKE44.js} +3 -3
- package/dist/chunk-V46JKE44.js.map +1 -0
- package/dist/{chunk-SUPUPSBE.js → chunk-ZDCJZCNO.js} +9 -8
- package/dist/chunk-ZDCJZCNO.js.map +1 -0
- package/dist/dev.d.ts +9 -6
- package/dist/dev.js +5 -5
- package/dist/dev.js.map +1 -1
- package/dist/html.d.ts +1 -1
- package/dist/html.js +5 -5
- package/dist/html.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +11 -11
- package/dist/jsx-runtime.js +5 -5
- package/dist/list.d.ts +1 -1
- package/dist/list.js +273 -211
- package/dist/list.js.map +1 -1
- package/dist/overlay.d.ts +190 -280
- package/dist/overlay.js +401 -361
- package/dist/overlay.js.map +1 -1
- package/dist/remount.d.ts +5 -3
- package/dist/remount.js +29 -10
- package/dist/remount.js.map +1 -1
- package/dist/router.d.ts +1 -1
- package/dist/router.js +44 -22
- package/dist/router.js.map +1 -1
- package/dist/scope.d.ts +4 -3
- package/dist/scope.js +10 -10
- package/dist/scope.js.map +1 -1
- package/dist/testing.js +4 -4
- package/dist/timing.d.ts +3 -2
- package/dist/timing.js +5 -5
- package/dist/timing.js.map +1 -1
- package/llms.txt +7 -4
- package/package.json +12 -10
- package/dist/chunk-MRYM3O3V.js.map +0 -1
- package/dist/chunk-SAYPJ6XR.js.map +0 -1
- package/dist/chunk-SRWQKB33.js.map +0 -1
- package/dist/chunk-SUPUPSBE.js.map +0 -1
- package/dist/chunk-U32TFTGZ.js.map +0 -1
- package/dist/chunk-VVDJLWMP.js.map +0 -1
- package/dist/chunk-YHH7OUFA.js.map +0 -1
- /package/dist/{attrSelector-Cmu2ZoGO.d.ts → attr-Cmu2ZoGO.d.ts} +0 -0
package/dist/list.js
CHANGED
|
@@ -1,226 +1,214 @@
|
|
|
1
|
-
import { ARRAY_SIGNAL_BRAND } from './chunk-
|
|
2
|
-
import { moveNode, mount } from './chunk-
|
|
3
|
-
import './chunk-QIP723L4.js';
|
|
4
|
-
import './chunk-YHH7OUFA.js';
|
|
5
|
-
import './chunk-SUPUPSBE.js';
|
|
6
|
-
import { effect } from './chunk-3APBEVHF.js';
|
|
7
|
-
import './chunk-GY4XV2UV.js';
|
|
8
|
-
import './chunk-VVDJLWMP.js';
|
|
1
|
+
import { ARRAY_SIGNAL_BRAND } from './chunk-LVH3GC6B.js';
|
|
2
|
+
import { captureFocus, restoreFocus, moveNode, mount } from './chunk-SVATPF5R.js';
|
|
9
3
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
import { effect } from './chunk-U6FK33SG.js';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
// src/list-row-controller.ts
|
|
11
|
+
var NOOP = () => {
|
|
12
|
+
};
|
|
13
|
+
function createListRowController(options) {
|
|
14
|
+
const { container, key, render, tag, endAnchor } = options;
|
|
20
15
|
const rows = /* @__PURE__ */ new Map();
|
|
21
16
|
const order = [];
|
|
22
|
-
let items = [];
|
|
23
|
-
let disposed = false;
|
|
24
|
-
let rafPending = false;
|
|
25
|
-
let firstRender = true;
|
|
26
|
-
const patchSource = source;
|
|
27
|
-
const granularEligible = virtualize === void 0 && patchSource[ARRAY_SIGNAL_BRAND] === true;
|
|
28
|
-
const container = virtualize === void 0 ? parent : document.createElement("div");
|
|
29
|
-
if (virtualize !== void 0) {
|
|
30
|
-
if (virtualize.containerClass !== void 0) container.className = virtualize.containerClass;
|
|
31
|
-
if (virtualize.containerId !== void 0) container.id = virtualize.containerId;
|
|
32
|
-
parent.appendChild(container);
|
|
33
|
-
}
|
|
34
|
-
const NOOP = () => {
|
|
35
|
-
};
|
|
36
17
|
const asElementRow = (rendered) => {
|
|
37
18
|
if (rendered instanceof HTMLElement) return { el: rendered, dispose: NOOP };
|
|
38
19
|
if (rendered !== null && typeof rendered === "object" && "el" in rendered && rendered.el instanceof HTMLElement) {
|
|
39
|
-
const
|
|
40
|
-
return { el:
|
|
20
|
+
const row = rendered;
|
|
21
|
+
return { el: row.el, dispose: row.dispose ?? NOOP, update: row.update };
|
|
41
22
|
}
|
|
42
23
|
return null;
|
|
43
24
|
};
|
|
44
25
|
const makeRow = (item) => {
|
|
45
26
|
const elementRow = asElementRow(render(item));
|
|
46
27
|
if (elementRow !== null) {
|
|
47
|
-
return {
|
|
28
|
+
return {
|
|
29
|
+
el: elementRow.el,
|
|
30
|
+
item,
|
|
31
|
+
dispose: elementRow.dispose,
|
|
32
|
+
elementMode: true,
|
|
33
|
+
update: elementRow.update
|
|
34
|
+
};
|
|
48
35
|
}
|
|
49
36
|
const el = document.createElement(tag);
|
|
50
37
|
const dispose2 = mount(el, () => render(item));
|
|
51
38
|
return { el, item, dispose: dispose2, elementMode: false };
|
|
52
39
|
};
|
|
53
|
-
const reconcileItem = (row,
|
|
40
|
+
const reconcileItem = (row, item) => {
|
|
54
41
|
if (row.item === item) return row;
|
|
42
|
+
const oldKey = key(row.item);
|
|
43
|
+
const newKey = key(item);
|
|
55
44
|
if (row.elementMode) {
|
|
56
45
|
row.item = item;
|
|
46
|
+
if (newKey !== oldKey) {
|
|
47
|
+
rows.delete(oldKey);
|
|
48
|
+
rows.set(newKey, row);
|
|
49
|
+
}
|
|
57
50
|
row.update?.(item);
|
|
58
51
|
return row;
|
|
59
52
|
}
|
|
60
53
|
row.dispose();
|
|
61
54
|
row.el.remove();
|
|
62
|
-
rows.delete(
|
|
55
|
+
rows.delete(oldKey);
|
|
63
56
|
const fresh = makeRow(item);
|
|
64
|
-
rows.set(
|
|
57
|
+
rows.set(newKey, fresh);
|
|
65
58
|
return fresh;
|
|
66
59
|
};
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
row.el.remove();
|
|
74
|
-
rows.delete(k);
|
|
75
|
-
}
|
|
60
|
+
const preserveFocus = (operation) => {
|
|
61
|
+
const focus = captureFocus(container);
|
|
62
|
+
try {
|
|
63
|
+
operation();
|
|
64
|
+
} finally {
|
|
65
|
+
if (focus !== null) restoreFocus(focus);
|
|
76
66
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
67
|
+
};
|
|
68
|
+
const sync = (visible) => {
|
|
69
|
+
preserveFocus(() => {
|
|
70
|
+
const wanted = /* @__PURE__ */ new Set();
|
|
71
|
+
for (const item of visible) wanted.add(key(item));
|
|
72
|
+
for (const [rowKey, row] of rows) {
|
|
73
|
+
if (!wanted.has(rowKey)) {
|
|
74
|
+
row.dispose();
|
|
75
|
+
row.el.remove();
|
|
76
|
+
rows.delete(rowKey);
|
|
77
|
+
}
|
|
87
78
|
}
|
|
88
|
-
order.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
79
|
+
order.length = 0;
|
|
80
|
+
for (const item of visible) {
|
|
81
|
+
const rowKey = key(item);
|
|
82
|
+
const existing = rows.get(rowKey);
|
|
83
|
+
const row = existing === void 0 ? makeRow(item) : reconcileItem(existing, item);
|
|
84
|
+
if (existing === void 0) rows.set(rowKey, row);
|
|
85
|
+
order.push(row);
|
|
95
86
|
}
|
|
96
|
-
ref =
|
|
97
|
-
|
|
87
|
+
let ref = endAnchor();
|
|
88
|
+
for (let index = order.length - 1; index >= 0; index--) {
|
|
89
|
+
const el = order[index].el;
|
|
90
|
+
if (el.parentNode !== container || el.nextSibling !== ref) moveNode(container, el, ref);
|
|
91
|
+
ref = el;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
98
94
|
};
|
|
99
95
|
const applyPatches = (patches) => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const newKey = key(patch.item);
|
|
121
|
-
current.item = patch.item;
|
|
122
|
-
if (newKey !== oldKey) {
|
|
123
|
-
rows.delete(oldKey);
|
|
124
|
-
rows.set(newKey, current);
|
|
125
|
-
}
|
|
126
|
-
current.update?.(patch.item);
|
|
127
|
-
} else {
|
|
128
|
-
current.dispose();
|
|
129
|
-
current.el.remove();
|
|
130
|
-
rows.delete(key(current.item));
|
|
131
|
-
const row = makeRow(patch.item);
|
|
132
|
-
rows.set(key(patch.item), row);
|
|
96
|
+
preserveFocus(() => {
|
|
97
|
+
for (const patch of patches) {
|
|
98
|
+
if (patch.type === "insert") {
|
|
99
|
+
const row = makeRow(patch.item);
|
|
100
|
+
rows.set(key(patch.item), row);
|
|
101
|
+
order.splice(patch.index, 0, row);
|
|
102
|
+
container.insertBefore(row.el, order[patch.index + 1]?.el ?? endAnchor());
|
|
103
|
+
} else if (patch.type === "remove") {
|
|
104
|
+
const [row] = order.splice(patch.index, 1);
|
|
105
|
+
row.dispose();
|
|
106
|
+
row.el.remove();
|
|
107
|
+
rows.delete(key(row.item));
|
|
108
|
+
} else if (patch.type === "move") {
|
|
109
|
+
const [row] = order.splice(patch.from, 1);
|
|
110
|
+
order.splice(patch.to, 0, row);
|
|
111
|
+
moveNode(container, row.el, order[patch.to + 1]?.el ?? endAnchor());
|
|
112
|
+
} else if (patch.type === "update") {
|
|
113
|
+
const current = order[patch.index];
|
|
114
|
+
const row = reconcileItem(current, patch.item);
|
|
115
|
+
if (row !== current) {
|
|
133
116
|
order[patch.index] = row;
|
|
134
117
|
container.insertBefore(row.el, order[patch.index + 1]?.el ?? endAnchor());
|
|
135
118
|
}
|
|
136
119
|
}
|
|
137
120
|
}
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
const dispose = (removeElements) => {
|
|
124
|
+
for (const row of rows.values()) {
|
|
125
|
+
row.dispose();
|
|
126
|
+
if (removeElements) row.el.remove();
|
|
138
127
|
}
|
|
128
|
+
rows.clear();
|
|
129
|
+
order.length = 0;
|
|
139
130
|
};
|
|
140
|
-
|
|
131
|
+
return { order, sync, applyPatches, dispose };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// src/list-virtualization-controller.ts
|
|
135
|
+
function createListVirtualizationController(options) {
|
|
136
|
+
const { parent, container, virtualize, key, rows } = options;
|
|
137
|
+
const overscan = virtualize.overscan ?? 3;
|
|
138
|
+
const { minRows, rowHeight } = virtualize;
|
|
139
|
+
const contentVisibility = virtualize.mode === "content-visibility";
|
|
141
140
|
const fixedHeight = typeof rowHeight === "number" ? rowHeight : null;
|
|
142
141
|
const measuring = typeof rowHeight === "object" && rowHeight !== null;
|
|
143
142
|
const measured = /* @__PURE__ */ new Map();
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
};
|
|
148
|
-
const variableHeightAt = fixedHeight !== null ? null : measuring ? (index) => {
|
|
149
|
-
const k = key(items[index]);
|
|
150
|
-
return measured.has(k) ? measured.get(k) : estimateAt(index);
|
|
151
|
-
} : (index) => rowHeight(items[index], index);
|
|
152
|
-
const intrinsicSizeAt = (index) => fixedHeight !== null ? fixedHeight : variableHeightAt(index);
|
|
143
|
+
const indexByKey = /* @__PURE__ */ new Map();
|
|
144
|
+
const renderSubscribers = /* @__PURE__ */ new Set();
|
|
145
|
+
let items = [];
|
|
153
146
|
let offsets = [0];
|
|
154
147
|
let heightsDirty = true;
|
|
155
|
-
const indexByKey = /* @__PURE__ */ new Map();
|
|
156
148
|
let pendingAnchorDelta = 0;
|
|
149
|
+
let rafPending = false;
|
|
150
|
+
let disposed = false;
|
|
151
|
+
const estimateAt = (index) => {
|
|
152
|
+
const estimate = rowHeight.estimate;
|
|
153
|
+
return typeof estimate === "function" ? estimate(items[index], index) : estimate;
|
|
154
|
+
};
|
|
155
|
+
const variableHeightAt = fixedHeight !== null ? null : measuring ? (index) => measured.get(key(items[index])) ?? estimateAt(index) : (index) => rowHeight(items[index], index);
|
|
156
|
+
const intrinsicSizeAt = (index) => fixedHeight ?? variableHeightAt(index);
|
|
157
157
|
const rebuildOffsets = () => {
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
offsets = new Array(total + 1);
|
|
158
|
+
const heightAt = variableHeightAt;
|
|
159
|
+
offsets = new Array(items.length + 1);
|
|
161
160
|
offsets[0] = 0;
|
|
162
161
|
if (measuring) indexByKey.clear();
|
|
163
|
-
for (let
|
|
164
|
-
offsets[
|
|
165
|
-
if (measuring) indexByKey.set(key(items[
|
|
162
|
+
for (let index = 0; index < items.length; index++) {
|
|
163
|
+
offsets[index + 1] = offsets[index] + heightAt(index);
|
|
164
|
+
if (measuring) indexByKey.set(key(items[index]), index);
|
|
166
165
|
}
|
|
167
166
|
if (measuring) {
|
|
168
|
-
for (const
|
|
167
|
+
for (const rowKey of measured.keys()) {
|
|
168
|
+
if (!indexByKey.has(rowKey)) measured.delete(rowKey);
|
|
169
|
+
}
|
|
169
170
|
}
|
|
170
171
|
};
|
|
171
172
|
const findStart = (target, total) => {
|
|
172
|
-
let
|
|
173
|
-
let
|
|
174
|
-
while (
|
|
175
|
-
const
|
|
176
|
-
if (offsets[
|
|
177
|
-
else
|
|
173
|
+
let low = 0;
|
|
174
|
+
let high = total;
|
|
175
|
+
while (low < high) {
|
|
176
|
+
const middle = low + high + 1 >> 1;
|
|
177
|
+
if (offsets[middle] <= target) low = middle;
|
|
178
|
+
else high = middle - 1;
|
|
178
179
|
}
|
|
179
|
-
return
|
|
180
|
+
return low;
|
|
180
181
|
};
|
|
181
182
|
const findEnd = (target, total) => {
|
|
182
|
-
let
|
|
183
|
-
let
|
|
184
|
-
while (
|
|
185
|
-
const
|
|
186
|
-
if (offsets[
|
|
187
|
-
else
|
|
183
|
+
let low = 0;
|
|
184
|
+
let high = total;
|
|
185
|
+
while (low < high) {
|
|
186
|
+
const middle = low + high >> 1;
|
|
187
|
+
if (offsets[middle] >= target) high = middle;
|
|
188
|
+
else low = middle + 1;
|
|
188
189
|
}
|
|
189
|
-
return
|
|
190
|
+
return low;
|
|
190
191
|
};
|
|
191
|
-
const
|
|
192
|
+
const sizeRows = (start2) => {
|
|
192
193
|
if (measuring) return;
|
|
193
|
-
for (let
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
order[
|
|
194
|
+
for (let index = 0; index < rows.order.length; index++) {
|
|
195
|
+
const absoluteIndex = start2 + index;
|
|
196
|
+
const height = fixedHeight ?? offsets[absoluteIndex + 1] - offsets[absoluteIndex];
|
|
197
|
+
rows.order[index].el.style.height = `${height}px`;
|
|
197
198
|
}
|
|
198
199
|
};
|
|
199
|
-
const
|
|
200
|
-
const renderWindow = () => {
|
|
201
|
-
if (virtualize === void 0) {
|
|
202
|
-
if (granularEligible) {
|
|
203
|
-
const patches = patchSource._consumePatches();
|
|
204
|
-
if (!firstRender && patches.length > 0 && !patches.some((p) => p.type === "replace")) {
|
|
205
|
-
applyPatches(patches);
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
syncRows(items);
|
|
210
|
-
firstRender = false;
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
200
|
+
const renderCurrent = () => {
|
|
213
201
|
if (contentVisibility) {
|
|
214
|
-
|
|
215
|
-
for (let
|
|
216
|
-
const el = order[
|
|
202
|
+
rows.sync(items);
|
|
203
|
+
for (let index = 0; index < rows.order.length; index++) {
|
|
204
|
+
const el = rows.order[index].el;
|
|
217
205
|
el.style.contentVisibility = "auto";
|
|
218
|
-
el.style.containIntrinsicSize = `0 ${intrinsicSizeAt(
|
|
206
|
+
el.style.containIntrinsicSize = `0 ${intrinsicSizeAt(index)}px`;
|
|
219
207
|
}
|
|
220
208
|
return;
|
|
221
209
|
}
|
|
222
210
|
const total = items.length;
|
|
223
|
-
let
|
|
211
|
+
let start2;
|
|
224
212
|
let end;
|
|
225
213
|
let padTop;
|
|
226
214
|
let padBottom;
|
|
@@ -229,40 +217,38 @@ function bindList(parent, source, options) {
|
|
|
229
217
|
rebuildOffsets();
|
|
230
218
|
heightsDirty = false;
|
|
231
219
|
}
|
|
232
|
-
|
|
220
|
+
start2 = 0;
|
|
233
221
|
end = total;
|
|
234
222
|
padTop = 0;
|
|
235
223
|
padBottom = 0;
|
|
224
|
+
} else if (fixedHeight !== null) {
|
|
225
|
+
const viewportBottom = parent.scrollTop + parent.clientHeight;
|
|
226
|
+
start2 = Math.max(0, Math.floor(parent.scrollTop / fixedHeight) - overscan);
|
|
227
|
+
end = Math.min(total, Math.ceil(viewportBottom / fixedHeight) + overscan);
|
|
228
|
+
padTop = start2 * fixedHeight;
|
|
229
|
+
padBottom = Math.max(0, total - end) * fixedHeight;
|
|
236
230
|
} else {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
start = Math.max(0, Math.floor(scrollTop / fixedHeight) - overscan);
|
|
241
|
-
end = Math.min(total, Math.ceil(viewportBottom / fixedHeight) + overscan);
|
|
242
|
-
padTop = start * fixedHeight;
|
|
243
|
-
padBottom = Math.max(0, total - end) * fixedHeight;
|
|
244
|
-
} else {
|
|
245
|
-
if (heightsDirty) {
|
|
246
|
-
rebuildOffsets();
|
|
247
|
-
heightsDirty = false;
|
|
248
|
-
}
|
|
249
|
-
start = Math.max(0, findStart(scrollTop, total) - overscan);
|
|
250
|
-
end = Math.min(total, findEnd(viewportBottom, total) + overscan);
|
|
251
|
-
padTop = offsets[start];
|
|
252
|
-
padBottom = offsets[total] - offsets[end];
|
|
231
|
+
if (heightsDirty) {
|
|
232
|
+
rebuildOffsets();
|
|
233
|
+
heightsDirty = false;
|
|
253
234
|
}
|
|
235
|
+
const viewportBottom = parent.scrollTop + parent.clientHeight;
|
|
236
|
+
start2 = Math.max(0, findStart(parent.scrollTop, total) - overscan);
|
|
237
|
+
end = Math.min(total, findEnd(viewportBottom, total) + overscan);
|
|
238
|
+
padTop = offsets[start2];
|
|
239
|
+
padBottom = offsets[total] - offsets[end];
|
|
254
240
|
}
|
|
255
|
-
|
|
256
|
-
|
|
241
|
+
rows.sync(items.slice(start2, end));
|
|
242
|
+
sizeRows(start2);
|
|
257
243
|
container.style.paddingTop = `${padTop}px`;
|
|
258
244
|
container.style.paddingBottom = `${padBottom}px`;
|
|
259
|
-
for (const
|
|
245
|
+
for (const callback of renderSubscribers) callback();
|
|
260
246
|
};
|
|
261
|
-
const
|
|
262
|
-
items =
|
|
247
|
+
const render = (nextItems) => {
|
|
248
|
+
items = nextItems;
|
|
263
249
|
heightsDirty = true;
|
|
264
|
-
|
|
265
|
-
}
|
|
250
|
+
renderCurrent();
|
|
251
|
+
};
|
|
266
252
|
const scheduleRender = () => {
|
|
267
253
|
if (rafPending) return;
|
|
268
254
|
rafPending = true;
|
|
@@ -273,51 +259,128 @@ function bindList(parent, source, options) {
|
|
|
273
259
|
parent.scrollTop += pendingAnchorDelta;
|
|
274
260
|
pendingAnchorDelta = 0;
|
|
275
261
|
}
|
|
276
|
-
|
|
262
|
+
renderCurrent();
|
|
277
263
|
});
|
|
278
264
|
};
|
|
279
|
-
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
265
|
+
const resizeObserver = !contentVisibility && globalThis.ResizeObserver !== void 0 ? new globalThis.ResizeObserver(scheduleRender) : void 0;
|
|
266
|
+
const start = () => {
|
|
267
|
+
if (contentVisibility) return;
|
|
268
|
+
parent.addEventListener("scroll", scheduleRender);
|
|
269
|
+
resizeObserver?.observe(parent);
|
|
270
|
+
};
|
|
271
|
+
const setHeight = (rowKey, height) => {
|
|
284
272
|
if (!measuring || contentVisibility) return;
|
|
285
|
-
const
|
|
286
|
-
if (
|
|
287
|
-
const oldHeight = measured.
|
|
273
|
+
const index = indexByKey.get(rowKey);
|
|
274
|
+
if (index === void 0) return;
|
|
275
|
+
const oldHeight = measured.get(rowKey) ?? estimateAt(index);
|
|
288
276
|
if (height === oldHeight) return;
|
|
289
|
-
measured.set(
|
|
290
|
-
if (offsets[
|
|
277
|
+
measured.set(rowKey, height);
|
|
278
|
+
if (offsets[index + 1] <= parent.scrollTop) pendingAnchorDelta += height - oldHeight;
|
|
291
279
|
heightsDirty = true;
|
|
292
280
|
scheduleRender();
|
|
293
281
|
};
|
|
294
|
-
const
|
|
282
|
+
const onRender = (callback) => {
|
|
283
|
+
renderSubscribers.add(callback);
|
|
284
|
+
return () => renderSubscribers.delete(callback);
|
|
285
|
+
};
|
|
286
|
+
const dispose = () => {
|
|
295
287
|
disposed = true;
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
row.dispose();
|
|
299
|
-
if (virtualize === void 0) row.el.remove();
|
|
300
|
-
}
|
|
301
|
-
rows.clear();
|
|
288
|
+
parent.removeEventListener("scroll", scheduleRender);
|
|
289
|
+
resizeObserver?.disconnect();
|
|
302
290
|
renderSubscribers.clear();
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
291
|
+
};
|
|
292
|
+
return { contentVisibility, render, start, setHeight, onRender, dispose };
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// src/list.ts
|
|
296
|
+
var NOOP2 = () => {
|
|
297
|
+
};
|
|
298
|
+
function assertUniqueListKeys(items, key) {
|
|
299
|
+
const firstIndex = /* @__PURE__ */ new Map();
|
|
300
|
+
for (let index = 0; index < items.length; index++) {
|
|
301
|
+
const rowKey = key(items[index]);
|
|
302
|
+
const first = firstIndex.get(rowKey);
|
|
303
|
+
if (first !== void 0) {
|
|
304
|
+
const displayed = typeof rowKey === "string" ? JSON.stringify(rowKey) : String(rowKey);
|
|
305
|
+
throw new Error(
|
|
306
|
+
`bindList: duplicate key ${displayed} at indices ${first} and ${index} \u2014 every row key must be unique.`
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
firstIndex.set(rowKey, index);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
function bindList(parent, source, options) {
|
|
313
|
+
const { key, render, tag = "div", virtualize, before } = options;
|
|
314
|
+
let firstRender = true;
|
|
315
|
+
let forceSnapshot = false;
|
|
316
|
+
const patchSource = source;
|
|
317
|
+
const granularEligible = virtualize === void 0 && patchSource[ARRAY_SIGNAL_BRAND] === true;
|
|
318
|
+
const container = virtualize === void 0 ? parent : document.createElement("div");
|
|
319
|
+
if (virtualize !== void 0) {
|
|
320
|
+
if (virtualize.containerClass !== void 0) container.className = virtualize.containerClass;
|
|
321
|
+
if (virtualize.containerId !== void 0) container.id = virtualize.containerId;
|
|
322
|
+
}
|
|
323
|
+
const endAnchor = () => {
|
|
324
|
+
if (virtualize !== void 0 || before === void 0) return null;
|
|
325
|
+
return (typeof before === "function" ? before() : before) ?? null;
|
|
326
|
+
};
|
|
327
|
+
const rows = createListRowController({ container, key, render, tag, endAnchor });
|
|
328
|
+
const virtualization = virtualize === void 0 ? void 0 : createListVirtualizationController({ parent, container, virtualize, key, rows });
|
|
329
|
+
const renderItems = (items) => {
|
|
330
|
+
if (virtualization !== void 0) {
|
|
331
|
+
virtualization.render(items);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
if (granularEligible) {
|
|
335
|
+
const patches = patchSource._consumePatches();
|
|
336
|
+
if (!firstRender && !forceSnapshot && patches.length > 0 && !patches.some((patch) => patch.type === "replace")) {
|
|
337
|
+
try {
|
|
338
|
+
rows.applyPatches(patches);
|
|
339
|
+
} catch (error) {
|
|
340
|
+
forceSnapshot = true;
|
|
341
|
+
throw error;
|
|
342
|
+
}
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
rows.sync(items);
|
|
347
|
+
firstRender = false;
|
|
348
|
+
forceSnapshot = false;
|
|
349
|
+
};
|
|
350
|
+
const stopEffect = effect(() => {
|
|
351
|
+
const items = source.value;
|
|
352
|
+
try {
|
|
353
|
+
assertUniqueListKeys(items, key);
|
|
354
|
+
} catch (error) {
|
|
355
|
+
if (granularEligible) {
|
|
356
|
+
patchSource._consumePatches();
|
|
357
|
+
forceSnapshot = true;
|
|
358
|
+
}
|
|
359
|
+
throw error;
|
|
360
|
+
}
|
|
361
|
+
renderItems(items);
|
|
362
|
+
});
|
|
363
|
+
if (virtualization !== void 0) {
|
|
364
|
+
parent.appendChild(container);
|
|
365
|
+
virtualization.start();
|
|
366
|
+
}
|
|
367
|
+
const dispose = (() => {
|
|
368
|
+
stopEffect();
|
|
369
|
+
rows.dispose(virtualization === void 0);
|
|
370
|
+
if (virtualization !== void 0) {
|
|
371
|
+
virtualization.dispose();
|
|
306
372
|
container.remove();
|
|
307
373
|
VIRTUAL_INTERNALS.delete(handle);
|
|
308
374
|
}
|
|
309
375
|
});
|
|
310
376
|
const handle = dispose;
|
|
311
|
-
handle.setHeight = setHeight;
|
|
312
|
-
if (
|
|
377
|
+
handle.setHeight = virtualization?.setHeight ?? NOOP2;
|
|
378
|
+
if (virtualization !== void 0) {
|
|
313
379
|
handle.container = container;
|
|
314
|
-
if (!contentVisibility) {
|
|
380
|
+
if (!virtualization.contentVisibility) {
|
|
315
381
|
VIRTUAL_INTERNALS.set(handle, {
|
|
316
|
-
visibleRows: () => order.map((row) => ({ key: key(row.item), el: row.el })),
|
|
317
|
-
onRender:
|
|
318
|
-
renderSubscribers.add(cb);
|
|
319
|
-
return () => renderSubscribers.delete(cb);
|
|
320
|
-
}
|
|
382
|
+
visibleRows: () => rows.order.map((row) => ({ key: key(row.item), el: row.el })),
|
|
383
|
+
onRender: virtualization.onRender
|
|
321
384
|
});
|
|
322
385
|
}
|
|
323
386
|
}
|
|
@@ -327,8 +390,7 @@ var VIRTUAL_INTERNALS = /* @__PURE__ */ new WeakMap();
|
|
|
327
390
|
function observeRowHeights(handle) {
|
|
328
391
|
const internals = VIRTUAL_INTERNALS.get(handle);
|
|
329
392
|
const RO = globalThis.ResizeObserver;
|
|
330
|
-
if (internals === void 0 || RO === void 0) return
|
|
331
|
-
};
|
|
393
|
+
if (internals === void 0 || RO === void 0) return NOOP2;
|
|
332
394
|
const keyByEl = /* @__PURE__ */ new WeakMap();
|
|
333
395
|
const observer = new RO((entries) => {
|
|
334
396
|
for (const entry of entries) {
|
|
@@ -352,5 +414,5 @@ function observeRowHeights(handle) {
|
|
|
352
414
|
}
|
|
353
415
|
|
|
354
416
|
export { bindList, observeRowHeights };
|
|
355
|
-
|
|
417
|
+
|
|
356
418
|
//# sourceMappingURL=list.js.map
|